package com.bonus.bracelet.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import com.alibaba.fastjson2.JSONObject;
import com.bonus.bracelet.mapper.EngineeringMapper;
import com.bonus.bracelet.service.IEngineeringService;
import com.bonus.common.core.constant.BusinessConstants;
import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.utils.ExcelStyleUtil;
import com.bonus.common.core.utils.ImportExcelUtils;
import com.bonus.common.core.utils.encryption.Sm4Utils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.entity.bracelet.exportVo.EngineeringExportVo;
import com.bonus.common.entity.bracelet.exportVo.GtExportVo;
import com.bonus.common.entity.bracelet.exportVo.PersonExportVo;
import com.bonus.common.entity.bracelet.importVo.GtImportVo;
import com.bonus.common.entity.bracelet.vo.*;
import com.bonus.common.security.utils.ValidatorsUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.*;

/**
 * IEngineeringService
 */
@Service(value = "IEngineeringService")
@Slf4j
public class EngineeringServiceImpl implements IEngineeringService {

    @Resource(name = "EngineeringMapper")
    private EngineeringMapper Mapper;

    @Resource(name = "ValidatorsUtils")
    private ValidatorsUtils validatorsUtils;

    @Override
    public List<EngineeringVo> getEngineeringLists(EngineeringVo data) {
        List<EngineeringVo> list = new ArrayList<>();
        try {
            list = Mapper.getEngineeringLists(data);
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return list;
    }
    @Value("${file.temp_file_path}")
    private String tempFilePath;

    /**
     * 根据工程id获得杆塔详细信息
     * @param vo
     * @return
     */
    @Override
    public List<GtVo> selectGtById(GtVo vo) {
        List<GtVo> list = new ArrayList<>();
        try {
            list = Mapper.selectGtById(vo);
        } catch (Exception e) {
            log.error("杆塔详情", e);
        }
        return list;
    }

    /**
     * 新增杆塔信息
     * @param vo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addGt(GtVo vo) {
        try {
            GtVo result = Mapper.isCodeExist(vo);
            if (result != null) {
                return AjaxResult.error("杆塔编号已存在");
            }
            int num =  Mapper.addGt(vo);
            if(num==1){
                return AjaxResult.success();
            }
            return AjaxResult.error("杆塔信息新增失败");
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
    }

    /**
     * 根据杆塔id获得详细信息
     * @param gtId
     * @return
     */
    @Override
    public AjaxResult selectGtId(Integer gtId) {
        try {
            GtVo vo = Mapper.selectGtId(gtId);
            if(vo!=null){
                return AjaxResult.success(vo);
            }else{
                return AjaxResult.error("查询不到该杆塔信息");
            }
        } catch (Exception e) {
            log.error("杆塔详情", e);
            return AjaxResult.error();
        }
    }

    /**
     * 修改杆塔
     * @param vo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult editGt(GtVo vo) {
        try {
            GtVo result = Mapper.isExist(vo);
            if (result != null) {
                return AjaxResult.error("杆塔编号已存在");
            }

           int num =  Mapper.updateGt(vo);
            if(num==1){
                return AjaxResult.success();
            }
            return AjaxResult.error("杆塔信息修改失败");
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
    }

    /**
     * 删除杆塔
     * @param gtId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deleteGt(int gtId) {
        try {
            int result = Mapper.deleteGt(gtId);
            if(result==1){
                return AjaxResult.success();
            }
            return AjaxResult.error("杆塔信息删除失败");
        } catch (Exception e) {
            log.error(e.toString(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
    }

    /**
     * 根据工程id获得详细信息
     * @param proId
     * @return
     */
    @Override
    public AjaxResult getEngineeringInfo(Long proId) {
        try {
            EngineeringVo vo = Mapper.getEngineeringInfo(proId);
            return AjaxResult.success(vo);
        } catch (Exception e) {
            log.error("工程详情", e);
            return AjaxResult.error();
        }
    }

    /**
     * 修改工程
     * @param vo
     * @return AjaxResult
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult editPro(EngineeringVo vo) {
        try {
            if(vo.getYzManage()==null || vo.getYzManage().equals("")){
                vo.setYzManage(null);
            }
            if(vo.getSgManage()==null || vo.getSgManage().equals("")){
                vo.setSgManage(null);
            }
            if(vo.getJlManage()==null || vo.getJlManage().equals("")){
                vo.setJlManage(null);
            }
            EngineeringVo result = Mapper.isNameExist(vo);
            if (result != null) {
                return AjaxResult.error("工程名称已存在");
            }

           int num =  Mapper.updatePro(vo);
            if(num==1){
                return AjaxResult.success();
            }
            return AjaxResult.error("工程信息修改失败");
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
    }

    /**
     * 新增工程信息
     * @param vo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addPro(EngineeringVo vo) {
        try {
            EngineeringVo result = Mapper.isAddNameExist(vo);
            if (result != null) {
                return AjaxResult.error("工程名称已存在");
            }
            int num =  Mapper.addPro(vo);
            if(num==1){
                return AjaxResult.success();
            }
            return AjaxResult.error("工程信息新增失败");
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
    }

    /**
     * 删除工程
     * @param proId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult deletePro(Long proId) {
        try {
            int result = Mapper.deletePro(proId);
            if(result==1){
                return AjaxResult.success();
            }
            return AjaxResult.error("工程信息删除失败");
        } catch (Exception e) {
            log.error(e.toString(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult excelUpload(MultipartFile file, HttpServletRequest request, HttpServletResponse response,Long proId) {
        List<String> errorFileLists = new ArrayList<>();
        try {
            List<JSONObject> lstObj = (List<JSONObject>) ImportExcelUtils.readExcel(file, GtImportVo.class, tempFilePath);
            List<GtVo> list = new ArrayList<>();
            if (CollectionUtils.isEmpty(lstObj)) {
                return AjaxResult.error("请勿导入空数据");
            }
            // 校验数据是否合法
            for (JSONObject obj : lstObj) {
                GtImportVo vo = new GtImportVo();
                GtVo gtVo = new GtVo();
                vo = setEngineeringData(vo, obj);
                BeanUtils.copyProperties(vo, gtVo);
                String validResult = validatorsUtils.valid(gtVo, GtVo.Query.class);
                if (StringUtils.isNotBlank(validResult)) {
                    return AjaxResult.error("第"+ obj.getString("rowNo") +"行" + validResult);
                }
                gtVo.setProId(proId);
                list.add(gtVo);
            }
            // 校验杆塔编号是否存在相同数据
            List<String> sameList = same(list,  "杆塔编号");
            String existData = isExistData(sameList);
            if (StringUtils.isNotBlank(existData)) {
                return AjaxResult.error(existData);
            }
            // 校验库中数据是否重复
            List<Map<String, String>> gtCodeIsExist = Mapper.gtCodeIsExist(new GtVo());
            for (GtVo vo : list) {
                if (idGtCodeIsExist(gtCodeIsExist, vo, 1)) {
                    return AjaxResult.error("第"+vo.getSerialNumber()+"行杆塔编号已存在");
                }

            }
            for (GtVo vo : list) {
                // 对数据进行导入
                Mapper.addGt(vo);
            }
        } catch (RuntimeException runtimeException) {
            if(runtimeException.getMessage() == null){
                return AjaxResult.error("模板中含有单元格数据格式不正确");
            }
            return AjaxResult.error(runtimeException.getMessage());
        } catch (Exception e) {
            log.error(e.toString(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error();
        }
        return AjaxResult.success();
    }

    /**
     * 杆塔数据赋值
     * @param vo
     * @param obj
     * @return
     */
    public GtImportVo setEngineeringData(GtImportVo vo, JSONObject obj) {
        vo.setSerialNumber(obj.getString("rowNum"));
//        vo.setName(handleData(obj.getString("name")));
        vo.setGtCode((handleData(obj.getString("gtCode"))));
        vo.setLon(handleData(obj.getString("lon")));
        vo.setLat(handleData(obj.getString("lat")));
        return vo;
    }

    public String handleData(String value){
        if(StringUtils.isNotBlank(value)){
            return value.trim();
        }
        return null;
    }

    public static List<String> same(List<GtVo> list, String name) {

        List<String> errList = new ArrayList<String>();
        Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < list.size(); i++) {
            String key =  list.get(i).getGtCode();
            if (key == null || Objects.equals("", key)) {
                continue;
            }
            String old = map.get(key);
            if (old != null) {
                map.put(key, old + "," + (i + 3));
            } else {
                map.put(key, "" + (i + 3));
            }
        }
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            String value = map.get(key);
            if (value.indexOf(",") != -1) {
                System.out.println(key + " 重复,行： " + value);
                errList.add(name + " 重复,重复行： " + value);
            }
        }
        return errList;
    }

    /**
     * excel表格是否存在相同数据
     *
     * @return String
     * @author cwchen
     * @date 2024/7/17 12:07
     */
    public String isExistData(List<String> sameList) {
        if (CollectionUtils.isNotEmpty(sameList)) {
            StringBuffer errStr = new StringBuffer();
            for (int j = 0; j < sameList.size(); j++) {
                errStr.append(sameList.get(j) + "\n");
            }
            return errStr.toString();
        }
        return null;
    }

    /**
     * 验证杆塔编号是否存在
     *
     * @param list
     * @return boolean
     */
    public boolean idGtCodeIsExist(List<Map<String, String>> list,GtVo vo, int type) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        } else {
            String gtCodeVo = vo.getGtCode();
            for (Map<String, String> map : list) {
                String value =  map.get("gtCode");
                if (Objects.equals(gtCodeVo, map.get("gtCode"))) {
                    return true;
                }
            }
            return false;
        }
    }

}
