package com.artfess.cqxy.contract.manager.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.artfess.base.context.BaseContext;
import com.artfess.base.feign.SystemConfigFeignService;
import com.artfess.base.feign.UCFeignService;
import com.artfess.base.manager.impl.BaseManagerImpl;
import com.artfess.base.model.CommonResult;
import com.artfess.base.query.*;
import com.artfess.base.util.*;
import com.artfess.cqxy.contract.dao.ContractDao;
import com.artfess.cqxy.contract.manager.ContractManager;
import com.artfess.cqxy.contract.manager.ItemManager;
import com.artfess.cqxy.contract.model.Contract;
import com.artfess.cqxy.contract.model.Item;
import com.artfess.cqxy.contract.vo.ContractVo;
import com.artfess.cqxy.processManagermant.model.ProgressManage;
import com.artfess.cqxy.projectManagement.enums.ProjectStatusEnum;
import com.artfess.cqxy.projectManagement.manager.ProjectManagementManager;
import com.artfess.cqxy.projectManagement.model.ProjectManagement;
import com.artfess.cqxy.search.enums.FunctionEnum;
import com.artfess.cqxy.search.manager.GlobalRetrievalManager;
import com.artfess.cqxy.search.model.GlobalRetrieval;
import com.artfess.cqxy.statistics.vo.StatisticsVo;
import com.artfess.cqxy.universal.manager.AccessoryManager;
import com.artfess.cqxy.universal.model.Accessory;
import com.artfess.cqxy.utils.BizUtils;
import com.artfess.cqxy.utils.ZipUtils;
import com.artfess.poi.util.ExcelUtil;
import com.artfess.sysConfig.persistence.manager.SysDictionaryManager;
import com.artfess.sysConfig.persistence.param.DictModel;
import com.artfess.uc.api.impl.util.ContextUtil;
import com.artfess.uc.api.model.IUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 合同管理表(BizContract)表服务实现类
 *
 * @author 黎沐华
 * @since 2022-02-26 10:35:04
 */
@Service
public class ContractManagerImpl extends BaseManagerImpl<ContractDao, Contract> implements ContractManager {

    @Autowired
    private ItemManager itemManager;

    @Autowired
    private ProjectManagementManager ppm;

    @Autowired
    private AccessoryManager am;

    @Autowired
    private SystemConfigFeignService scfs;

    @Autowired
    private SysDictionaryManager sdm;

    @Autowired
    private GlobalRetrievalManager grm;

    @Autowired
    private BaseContext baseContext;

    @Autowired
    private AccessoryManager accessoryManager;

    @Resource
    private UCFeignService ucFeignService;

    @Override
    public boolean saveContract(ContractVo vo) {
        // 获取字典
//        List<DictModel> contractType = sdm.queryDictListItemsByCode("htgl-htlb");

        // 处理合同信息默认值
        Contract contractData = vo.getContract();
        // 项目ID不能为空
        Assert.notNull(contractData.getProjectId(), "项目ID不能为空");
        Assert.notNull(contractData.getType(), "合同类别不能为空");
        String contractInvolved = contractData.getFirstParty();
        contractData.setContractInvolved(StringUtils.isEmpty(contractInvolved) ? ppm.get(contractData.getProjectId()).getProjectName() : contractInvolved);
        String firstParty = contractData.getFirstParty();
        contractData.setFirstParty(StringUtils.isEmpty(firstParty) ? "重庆西永微电子产业园区开发有限公司" : firstParty);
        String uniqueNumber = scfs.getNextIdByAlias("htwybh").replace("施工合同", contractData.getTypeValue());
        contractData.setUniqueNumber(uniqueNumber.substring(StringUtils.lastOrdinalIndexOf(uniqueNumber, "\"", 2) + 1, uniqueNumber.lastIndexOf("\"")));
        boolean contract = save(contractData);

        List<Item> items = null == vo.getContractItem() ? new ArrayList<>() : vo.getContractItem();
        for (Item ele : items) {
            ele.setContractId_(vo.getContract().getId());
            ele.setIsDele("0");
        }
        // 保存合同明细
        boolean item = items.size() == 0 || itemManager.saveOrUpdateBatch(items);
        //更新项目状态
        ppm.updateStatusById(contractData.getProjectId(), Integer.valueOf(ProjectStatusEnum.nine.getCode()));
        // 同步到检索表
        handleRetrieval(new GlobalRetrieval(), vo.getContract());
        return contract && item && handleAccessory(vo);
    }

    @Override
    public boolean updateContract(ContractVo vo) {
        boolean contract = updateById(vo.getContract());
        boolean item = false;
        if(null==vo.getContractItem()||vo.getContractItem().size()==0){
            item = true;
        }else{
            item = itemManager.saveOrUpdateBatch(vo.getContractItem());
        }
        // 同步到检索表
        GlobalRetrieval globalRetrieval= grm.getByBizId(vo.getContract().getId());
        handleRetrieval(BeanUtils.isEmpty(globalRetrieval) ?new GlobalRetrieval():globalRetrieval,vo.getContract());
        return contract && item && handleAccessory(vo);
    }

    /**
     * 同步到检索表
     * @param globalRetrieval 检索表对象
     * @param entity 合同对象
     */
    private void handleRetrieval(GlobalRetrieval globalRetrieval, Contract entity){
        ProjectManagement projectManagement = ppm.getById(entity.getProjectId());
        globalRetrieval.setProjectId(entity.getProjectId());
        globalRetrieval.setProjectName(projectManagement.getProjectName());
        globalRetrieval.setPersonCharge(projectManagement.getProjectManager());
        globalRetrieval.setArchivesType(1);
        globalRetrieval.setBizDataId(entity.getId());
        globalRetrieval.setFunctionCode(FunctionEnum.forteen.getCode());
        globalRetrieval.setFunctionName(FunctionEnum.forteen.getName());
        globalRetrieval.setBizTableName(FunctionEnum.forteen.getTableName());
        globalRetrieval.setDetailsRoteUrl(FunctionEnum.forteen.getTableRoteUrl());
        globalRetrieval.setTableRoteUrl(FunctionEnum.forteen.getTableRoteUrl());
        globalRetrieval.setTableApiUrl(FunctionEnum.forteen.getTableApiUrl());
        globalRetrieval.setDetailsApiUrl(FunctionEnum.forteen.getDetailsApiUrl());
        globalRetrieval.setFunctionPath(FunctionEnum.forteen.getFunctionPath());
        globalRetrieval.setDocumentNumber(entity.getContractNumber());
        globalRetrieval.setName(entity.getName());
        globalRetrieval.setSearchTitle(entity.getName()+"_"+entity.getContractNumber()+"_"+entity.getDecisionDocuments()+"_"+
                entity.getContractInvolved()+"_"+entity.getFirstParty()+"_"+entity.getSecondParty()+"_"+entity.getThirdParty()+"_"+
                entity.getUniqueNumber()+"_"+entity.getContractExceptionLog()+"_"+entity.getContractSchedule()+"_"+entity.getTreatyContents()+"_"+
                entity.getContractKeeper()+"_"+entity.getContractStorage()+"_"+entity.getContractReceiver()+"_"+entity.getEstablishmentRemarks());
        grm.saveOrUpdate(globalRetrieval);
    }

    private boolean handleAccessory(ContractVo vo) {
        // 处理附件信息
        List<Accessory> flag = vo.getAccessoryInfo();//处理空指针
        List<Accessory> accessoryList = null == flag ? new ArrayList<>() : flag;
        for (Accessory ele : accessoryList) {
            ele.setSourceId(vo.getContract().getId());
            ele.setProjectId(vo.getContract().getProjectId());
            ele.setDirectory(ProjectStatusEnum.nine.getCode());
            ele.setGroup("Contract");
            ele.setNode(ProjectStatusEnum.nine.getCode());
            ele.setCreateBy(baseContext.getCurrentUserId());
            ele.setCreateName(baseContext.getCurrentUserName());
        }
        // 先清空该ID下的所有附件信息再添加
        am.removeBySourceId(vo.getContract().getId());
        // 如果没有附件则不进入添加
        return accessoryList.size() == 0 || am.saveBatch(accessoryList);
    }

    @Override
    public boolean removeContractByIds(List<String> ids) {
        boolean item = false, contract = false;
        for (String ele : ids) {
            UpdateWrapper<Item> itemWrapper = new UpdateWrapper<>();
            itemWrapper.set("IS_DELE_", "1").eq("CONTRACT_ID_", ele).eq("IS_DELE_", "0");
            List<Item> itemList = itemManager.getBaseMapper().selectList(new QueryWrapper<Item>().eq("CONTRACT_ID_", ele));
            item = itemList.size() == 0 || itemManager.update(itemWrapper);

            // 不会执行逻辑删除，故手动实现update
            UpdateWrapper<Contract> contractWrapper = new UpdateWrapper<>();
            contractWrapper.set("IS_DELE_", "1").eq("ID_", ele).eq("IS_DELE_", "0");
            contract = update(contractWrapper);
        }
        // 同步删除检索表中的信息
        for (String ele : ids) {
            grm.remove(1,ele);
        }
        return item && contract;
    }

    @Override
    public PageList<ContractVo> queryAllByPage(QueryFilter<Contract> queryFilter) {
        BizUtils.handleFilter(queryFilter, "bc", "pm");
        // 加入经办人查询权限，如果不是领导或者
        IUser user= ContextUtil.getCurrentUser();
        // 如果是管理员或者没有项目权限
        if(null != user){
//            String currentUserId = baseContext.getCurrentUserId();
            boolean disableAll = false;
            Integer userType = user.getUserType();
            String userId = user.getUserId();
            CommonResult<JsonNode> userNode = ucFeignService.getUserById(userId);
            if (userNode.getState()) {
                JsonNode userJsonNode = userNode.getValue();
                if(null != userJsonNode){
                    userType = userJsonNode.get("userType").asInt();
                }
            }
            // 1.先通过用户类型判断，过滤掉超级管理员之类的用户
            if(userType != null && userType !=0 && userType != 1){
                // 2.再通过角色判断，过滤掉没有对应角色权限的人员
                // 获取当前用户拥有的所有角色
                Set<String> set = new HashSet<String>();
                List<ObjectNode> list = ucFeignService.getRoleListByAccount(user.getAccount());
                if(BeanUtils.isNotEmpty(list)){
                    for (ObjectNode objectNode : list) {
                        set.add(objectNode.get("code").asText());
                    }
                }
                if(!set.contains("sysRole") && !set.contains("bld") && !set.contains("xmjl") && !set.contains("htgly")){
                    disableAll = true;
                }
            }
            if(disableAll){
                // 经办人模糊匹配或者为空的就可以查询
                String fullname = user.getFullname();
                queryFilter.addFilter("bc.contract_receiver_", fullname, QueryOP.LIKE, FieldRelation.AND, "contractReceiver");
                queryFilter.addFilter("bc.contract_receiver_", fullname, QueryOP.IS_NULL, FieldRelation.OR, "contractReceiver");
                queryFilter.addFilter("bc.contract_receiver_", "", QueryOP.EQUAL, FieldRelation.OR, "contractReceiver");
            }
        }
        IPage<Contract> contract =
                baseMapper.queryAllByPage(
                        convert2IPage(queryFilter.getPageBean()),
                        convert2Wrapper(queryFilter, currentModelClass()));

        List<Contract> contractList = null == contract.getRecords() ? new ArrayList<>() : contract.getRecords();
        List<ContractVo> voList = new ArrayList<>();
        for (Contract ele : contractList) {
//            if(ele.getContractAmount()!=null && ele.getContractAmount()!=""){
//              BigDecimal bigDecimal = new BigDecimal(ele.getContractAmount());
//              String amount = String.valueOf(bigDecimal.divide(new BigDecimal(10000),2,BigDecimal.ROUND_HALF_UP));
//              ele.setContractAmount(amount);
//            }

            QueryWrapper<Item> itemWrapper = new QueryWrapper<>();
            itemWrapper.eq("CONTRACT_ID_", ele.getId()).eq("IS_DELE_", "0");
            List<Item> items = itemManager.getBaseMapper().selectList(itemWrapper);

            List<Accessory> accessoryInfo = am.getAccessoryBySourceId(ele.getId());

            ProjectManagement projectManagement = ppm.getById(ele.getProjectId());
            ContractVo tempVo = new ContractVo(projectManagement, ele, items, accessoryInfo);
            voList.add(tempVo);
        }
        IPage<ContractVo> result = new Page<ContractVo>(contract.getCurrent(), contract.getSize(), contract.getTotal());
        result.setPages(contract.getPages());
        result.setRecords(voList);
        return new PageList<>(result);
    }

    @Override
    public PageList<Contract> queryContractByPage(QueryFilter<Contract> queryFilter) {
        BizUtils.handleFilter(queryFilter, "bc", "pm");
        IPage<Contract> contract =
                baseMapper.queryAllByPage(
                        convert2IPage(queryFilter.getPageBean()),
                        convert2Wrapper(queryFilter, currentModelClass()));
        return new PageList<>(contract);
    }

    @Override
    public ContractVo getVoById(String id) {
        QueryWrapper<Contract> contractWrapper = new QueryWrapper<>();
        contractWrapper.eq("ID_", id).eq("IS_DELE_", "0");
        Contract contract = baseMapper.selectOne(contractWrapper);

        if(BeanUtils.isEmpty(contract)){
            return null;
        }

        QueryWrapper<Item> itemWrapper = new QueryWrapper<>();
        itemWrapper.eq("CONTRACT_ID_", id).eq("IS_DELE_", "0");
        List<Item> items = itemManager.getBaseMapper().selectList(itemWrapper);

        List<Accessory> accessoryInfo = am.getAccessoryBySourceId(id);

        ProjectManagement projectManagement = ppm.getById(contract.getProjectId());

        return new ContractVo(projectManagement, contract, items, accessoryInfo);
    }

    @Override
    public void importExcelData(MultipartFile file, String projectId) {
        Assert.notNull(projectId,"项目ID不能为空");
        List<DictModel> secondLevelType = sdm. queryDictListItemsByCode("htgl-jsfs");
        List<DictModel> contractTypeDic = sdm. queryDictListItemsByCode("htgZ-htLb") ;

        try(InputStream inputStream = file.getInputStream();) {
            // 获取数据
            List<Contract> data = ExcelImportUtil.importExcel(inputStream,Contract.class,new ImportParams());
            data = removeNullData(data);
            for(Contract ele:data){
                ele.setProjectId(projectId);
                ele.setFirstParty(StringUtils.isBlank(ele.getFirstParty())?"重庆西永微电子产业园区开发有限公司":ele.getFirstParty());
                String type = BizUtils.getDicValueByCode(contractTypeDic, ele.getType());
                ele.setType(type);
                String uniqueNumber = scfs.getNextIdByAlias("htwybh").replace("施工合同", type);
                ele.setUniqueNumber(uniqueNumber.substring(StringUtils.lastOrdinalIndexOf(uniqueNumber, "\"", 2) + 1, uniqueNumber.lastIndexOf("\"")));
                ele.setSecondLevelType(BizUtils.getDicCodeByValue(secondLevelType,ele.getSecondLevelType()));
                // 保存数据 & 同步到检索表
                save(ele);
                handleRetrieval(new GlobalRetrieval(),ele);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private List<Contract> removeNullData(List<Contract> data){
        List<Contract> result = new ArrayList<>();
        data.forEach(e->{
            if(StringUtils.isNotEmpty(e.getName())){
                result.add(e);
            }
        });
        return result;
    }

    @Override
    public void exportDatatoExcel(QueryFilter<Contract> queryFilter, HttpServletResponse response) throws IOException {
        String fileName = "合同信息-导出结果";
        // 获取字典
        List<DictModel> payType = sdm.queryDictListItemsByCode("htgl-jsfs");
        List<DictModel> biddingChargeType = sdm.queryDictListItemsByCode("zbfs");
        List<DictModel> contractPType = sdm.queryDictListItemsByCode("htgl-htfl");
//        List<DictModel> contractTypeDic = sdm.queryDictListItemsByCode("htgl-htlb");

        // 获取数据
        BizUtils.handleFilter(queryFilter, "bc", "pm");
        List<Contract> data = baseMapper.queryAllByPage(
                        convert2IPage(new PageBean(0, -1, false)),
                        convert2Wrapper(queryFilter, currentModelClass())).
                getRecords();
        if(null==data||data.size()==0){
            throw new RuntimeException("没有要导出的的数据！");
        }

        // 翻译字典
        for(Contract ele : data){
            ele.setSecondLevelType(BizUtils.getDicValueByCode(payType, ele.getSecondLevelType()));
            ele.setBiddingChargeType(BizUtils.getDicValueByCode(biddingChargeType, ele.getBiddingChargeType()));
            ele.setMold(BizUtils.getDicValueByCode(contractPType, ele.getMold()));
//            ele.setType(BizUtils.getDicValueByCode(contractTypeDic, ele.getType()));
            ele.setType(ele.getTypeValue());
        }

        // EasyPoi 导出参数、样式、表格格式设置
        ExportParams exportParams = BizUtils.getExportParams(fileName);
        fileName += ".xlsx";

        // 导出下载excel文件
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, Contract.class, data);
        ExcelUtil.downloadExcel(workbook, fileName, response);
    }

    @Override
    public void updateProjectIdByProiectId(String oldProjectIds, String newProjectId) {
        UpdateWrapper<Contract> wrapper = new UpdateWrapper<Contract>()
                .set(StringUtils.isNotBlank(newProjectId), "PROJECT_ID_", newProjectId)
                .in("PROJECT_ID_", Arrays.asList(oldProjectIds.split(",")));
        this.update(wrapper);
    }

    @Override
    public List<Map<String, Object>> queryInvestment(StatisticsVo statisticsVo) {
        List<Map<String, Object>> list = this.baseMapper.queryInvestment(statisticsVo);
        List<DictModel> contractPType = sdm.queryDictListItemsByCode("htgl-htfl");
        if(null != list){
            for(DictModel dic : contractPType){
                String name = dic.getName();
                String value = dic.getValue();
                boolean isExistence = true;
                for (Map<String, Object> map : list) {
                    String type = map.get("type")==null? "" : String.valueOf(map.get("type"));
                    if(type.equalsIgnoreCase(value)){
                        map.put("typeName", name);
                        isExistence = false;
                        break;
                    }
                }
                if(isExistence){
                    Map<String, Object> map = new HashMap<>();
                    map.put("type", value);
                    map.put("typeName", name);
                    map.put("total", 0);
                    list.add(map);
                }
            }

        }
        return list;
    }

    @Override
    public BigDecimal queryConstructionAmount(String projectId) {
        BigDecimal constructionAmount = this.baseMapper.queryConstructionAmount(projectId);
        BigDecimal constructionAmountResult = BigDecimal.ZERO;
        if(null != constructionAmount && constructionAmount.compareTo(BigDecimal.ZERO) > 0){
            // 转为万元
            constructionAmountResult = constructionAmount.divide(new BigDecimal("10000"), 0, BigDecimal.ROUND_HALF_UP);
        }
        return constructionAmountResult;
    }

    @Override
    public BigDecimal queryConstructionAmount2(String projectId) {
        BigDecimal constructionAmount = this.baseMapper.queryConstructionAmount(projectId);
        BigDecimal constructionAmountResult = BigDecimal.ZERO;
        if(null != constructionAmount && constructionAmount.compareTo(BigDecimal.ZERO) > 0){
            // 转为万元
            constructionAmountResult = constructionAmount.divide(new BigDecimal("10000"), 2, BigDecimal.ROUND_HALF_UP);
        }
        return constructionAmountResult;
    }

    @Override
    public void downloadBatch(String projectId, List<String> contractIds, HttpServletResponse response){
        Assert.notNull(projectId, "项目ID不能为空");

        ProjectManagement project = ppm.getById(projectId);

        List<Accessory> accessoryList = Lists.newArrayList();
        if(BeanUtils.isNotEmpty(contractIds)){
            accessoryList = accessoryManager.list(new QueryWrapper<Accessory>().in("SOURCE_ID_", contractIds).eq("IS_DELE_","0").eq("GROUP_", "Contract"));
        }else {
            accessoryList = accessoryManager.list(new QueryWrapper<Accessory>().eq("PROJECT_ID_", projectId).eq("IS_DELE_","0").eq("GROUP_", "Contract"));
        }

        String zipName = "【"+project.getProjectName()+"】合同批量下载";

        String fileTemp = (FileUtil.getIoTmpdir() + "attachFiles/tempZip/" + zipName).replace("/", File.separator);
        //建立临时文件夹，存放文件
        File folder=new File(fileTemp);
        if(!folder.exists()) {
            folder.mkdirs();
        }

        try {
            // 下载文件
            for (Accessory accessory : accessoryList) {
                accessoryList.forEach(a->{
                    if (accessory.getName().equals(a.getName()) && !accessory.getFileSize().equals(a.getFileSize())){
                        accessory.setName(accessory.getName().replace("."+accessory.getSuffix(), "")+"【重名文件以日期标识】"+ LocalDateTimeUtil.format(accessory.getCreateTime(), DatePattern.CHINESE_DATE_TIME_PATTERN)+"."+accessory.getSuffix());
                    }
                });
                HttpUtil.downLoadByUrl(accessory.getUrl(), accessory.getName(), fileTemp);
            }

            // 打包
            FileOutputStream zipOut = new FileOutputStream(new File(fileTemp+".zip"));
            ZipUtils.toZip(fileTemp, zipOut, true);
            // 导出
            HttpUtil.downLoadFile(response, fileTemp + ".zip", zipName + ".zip");
            // 删除临时文件
            FileUtil.deleteDiretory(fileTemp.replace(zipName, ""));
        }catch (Exception e){
            e.printStackTrace();
            FileUtil.deleteDiretory(fileTemp.replace(zipName, ""));
        }
    }

}

