package com.sunxung.factoring.service.purchcontractmanagement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.*;
import com.sunxung.factoring.component.util.onlineConverter.OfficeConverterUtil;
import com.sunxung.factoring.dict.impl.FileModuleDict;
import com.sunxung.factoring.dict.impl.ProjectInitiationStatusDict;
import com.sunxung.factoring.entity.project.BusinessProcessingLog;
import com.sunxung.factoring.entity.purchcontractmanagement.*;
import com.sunxung.factoring.entity.purchcontractmanagement.vo.PurchContractChangeVo;
import com.sunxung.factoring.entity.salescontractmanagement.CSalesContractGoodsInfo;
import com.sunxung.factoring.entity.salescontractmanagement.SalesContractSupplementGoodsInfo;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.entity.tradingPlatform.Platform;
import com.sunxung.factoring.mapper.purchcontractmanagement.PurchContractSupplementInfoMapper;
import com.sunxung.factoring.service.project.BusinessAssigneeService;
import com.sunxung.factoring.service.project.BusinessProcessingLogService;
import com.sunxung.factoring.service.project.IProjectInformationService;
import com.sunxung.factoring.service.purchcontractmanagement.*;
import com.sunxung.factoring.service.salescontractmanagement.ISalesContractGoodsInfoHistoryService;
import com.sunxung.factoring.service.salescontractmanagement.ISalesContractSupplementGoodsInfoService;
import com.sunxung.factoring.service.salescontractmanagement.SalesContractGoodsInfoService;
import com.sunxung.factoring.service.salescontractmanagement.SalesContractService;
import com.sunxung.factoring.service.sys.DictionaryService;
import com.sunxung.factoring.service.sys.FileStorageService;
import com.sunxung.factoring.service.sys.ISysAttachmentRefService;
import com.sunxung.factoring.service.sys.UserService;
import com.sunxung.factoring.service.sys.flowable.FlowableService;
import com.sunxung.factoring.service.tradingPlatform.PlatformService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 采购合同-补充信息表 服务实现类
 * </p>
 *
 * @author daxian
 * @since 2022-03-14
 */
@Service("purch_contract_changeService")
public class PurchContractSupplementInfoServiceImpl extends ServiceImpl<PurchContractSupplementInfoMapper, PurchContractSupplementInfo> implements IPurchContractSupplementInfoService {

    @Autowired
    private PurchContractService purchContractService;

    @Autowired
    private DictionaryService dictService;

    @Autowired
    private BusinessAssigneeService assigneeService;

    @Autowired
    private FlowableService flowableService;

    @Autowired
    private IPurchContractSupplementGoodsInfoService supplementGoodsInfoService;

    @Autowired
    private SalesContractGoodsInfoService salesContractGoodsInfoService;

    @Autowired
    private ISalesContractSupplementGoodsInfoService salesContractSupplementGoodsInfoService;

    @Autowired
    private UserService userService;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private PurchContractBasicInfoService purchContractBasicInfoService;

    @Autowired
    private IPurchContractSupplementInfoHistoryService purchContractSupplementInfoHistoryService;

    @Autowired
    private IPurchContractSupplementGoodsInfoHistoryService purchContractSupplementGoodsInfoHistoryService;

    @Autowired
    private BusinessProcessingLogService processingLogService;

    @Autowired
    private IPurchContractSupplementElectronicInfoService purchContractSupplementElectronicInfoService;

    @Autowired
    private ISysAttachmentRefService sysAttachmentRefService;

    @Autowired
    @Resource(name = "projectInformationService")
    private IProjectInformationService projectInformationService;

    @Autowired
    private SalesContractService salesContractService;

    @Autowired
    private PlatformService platformService;

    @Autowired
    private BusinessProcessingLogService businessProcessingLogService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean change(PurchContractChangeVo vo) {

        ThreadLocalUtil.setUser(userService.getByLoginName("admin"));

        checkVo(vo);

        PurchContractManagement contractManagement = getContractManageByBusinessKey(vo);

        if (StringUtil.isEmpty(vo.getContractSupplementInfo().getSupplementContractNumber())) {
            String contractNumber = getContractNumber(contractManagement.getId());
            vo.getContractSupplementInfo().setSupplementContractNumber(contractNumber);
        }

        //补充信息
        PurchContractSupplementInfo  supplementInfo = vo.getContractSupplementInfo();
        supplementInfo.setPurchContractManagementId(vo.getBusinessKey());
        save(supplementInfo);
        //货物信息
        List<PurchContractSupplementGoodsInfo> supplementGoodsInfos = vo.getContractGoodsInfo();
        supplementGoodsInfos.forEach(c -> {
            c.setPurchContractSupplementInfoId(supplementInfo.getId());
            c.setSalesContractGoodsInfoId(c.getId());
        });
        supplementGoodsInfoService.saveBatch(supplementGoodsInfos);

        startProcess(vo);
        commitTask(vo);

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doSignChangeCallBack(String contractId) {

        //获取合同对应的最新签署信息
        PurchContractSupplementElectronicInfo electronicInfo = purchContractSupplementElectronicInfoService.lambdaQuery().eq(PurchContractSupplementElectronicInfo::getContractId, contractId).one();
        //获取最新签署信息，更新签署状态
        Long supplemementId = electronicInfo.getcPurchContractSupplementInfoId();
        PurchContractSupplementInfo supplementInfo = getById(supplemementId);
        if (electronicInfo.getCallBack() == 0) {
            //合同下载
            String contDownUrl = ElectronicSignatureUtil.downloadContract(contractId);
            FileStorage contractSupplementFile = fileStorageService.addFileStorageWithBelongAndName(contractId, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_SIGN_FILE, contDownUrl, supplemementId);
            fileStorageService.saveAttachmentRefByFileStorage(contractSupplementFile, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_SIGN_FILE, supplementInfo.getId());

            //合同归档
            ElectronicSignatureUtil.contractFiled(contractId);

            //电子文件签署线上出证下载
            String reportDownUrl = ElectronicSignatureUtil.complianceContractReport(contractId);
            FileStorage contractSupplementReportFile = fileStorageService.addFileStorageWithBelongAndName(contractId, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_FILE_REPORT, reportDownUrl, supplemementId);
            fileStorageService.saveAttachmentRefByFileStorage(contractSupplementReportFile, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_FILE_REPORT, supplementInfo.getId());

            electronicInfo.setSignStatus(true);
            electronicInfo.setCallBack(1);
            purchContractSupplementElectronicInfoService.updateById(electronicInfo);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doSignChangeCallBackByQuery(String contractId, Boolean downloadContract) {
        //
        //transactionId 是由 "SIGNPURCHCHANGE" +purchContractManagement.getId() + purch.getId() + "taskId" + "userId" 构成的
//        Long supplemementId = Long.valueOf(fdds[2]);
//        String taskId = fdds[3];


        //获取合同对应的最新签署信息
        PurchContractSupplementElectronicInfo electronicInfo = purchContractSupplementElectronicInfoService.lambdaQuery().eq(PurchContractSupplementElectronicInfo::getContractId, contractId).one();


        //获取最新签署信息，更新签署状态
        Long supplemementId = electronicInfo.getcPurchContractSupplementInfoId();
        PurchContractSupplementInfo supplementInfo = getById(supplemementId);

        if (electronicInfo.getCallBack() == 0 && downloadContract) {
            //合同下载
            String contDownUrl = ElectronicSignatureUtil.downloadContract(contractId);
            FileStorage contractSupplementFile = fileStorageService.addFileStorageWithBelongAndName(contractId, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_SIGN_FILE, contDownUrl, supplemementId);
            fileStorageService.saveAttachmentRefByFileStorage(contractSupplementFile, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_SIGN_FILE, supplementInfo.getId());

            //合同归档
            ElectronicSignatureUtil.contractFiled(contractId);

            //电子文件签署线上出证下载
            String reportDownUrl = ElectronicSignatureUtil.complianceContractReport(contractId);
            FileStorage contractSupplementReportFile = fileStorageService.addFileStorageWithBelongAndName(contractId, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_FILE_REPORT, reportDownUrl, supplemementId);
            fileStorageService.saveAttachmentRefByFileStorage(contractSupplementReportFile, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_FILE_REPORT, supplementInfo.getId());
            electronicInfo.setCallBack(1);
            purchContractSupplementElectronicInfoService.updateById(electronicInfo);
        }
        if (!electronicInfo.getSignStatus()) {
            electronicInfo.setSignStatus(true);
            purchContractSupplementElectronicInfoService.updateById(electronicInfo);
        }
    }

    @Override
    public PurchContractChangeVo getView(Long id) {
        PurchContractChangeVo vo = new PurchContractChangeVo();
        PurchContractSupplementInfoHistory purchContractSupplementInfoHistory = purchContractSupplementInfoHistoryService.getById(id);
        PurchContractSupplementInfo supplementInfo = new PurchContractSupplementInfo();
        BeanUtils.copyProperties(purchContractSupplementInfoHistory, supplementInfo);
        vo.setContractSupplementInfo(supplementInfo);

        List<PurchContractSupplementGoodsInfoHistory> purchContractSupplementGoodsInfoHistoryList = purchContractSupplementGoodsInfoHistoryService.list(
                new QueryWrapper<PurchContractSupplementGoodsInfoHistory>().eq("purch_contract_supplement_info_id", id)
        );
        if (purchContractSupplementGoodsInfoHistoryList != null && purchContractSupplementGoodsInfoHistoryList.size() > 0) {
            List<PurchContractSupplementGoodsInfo> purchContractSupplementGoodsInfoList = new ArrayList<>();
            for (PurchContractSupplementGoodsInfoHistory purchContractSupplementGoodsInfoHistory : purchContractSupplementGoodsInfoHistoryList) {
                PurchContractSupplementGoodsInfo purchContractSupplementGoodsInfo = new PurchContractSupplementGoodsInfo();
                BeanUtils.copyProperties(purchContractSupplementGoodsInfoHistory, purchContractSupplementGoodsInfo);
                purchContractSupplementGoodsInfoList.add(purchContractSupplementGoodsInfo);
            }
            vo.setContractGoodsInfo(purchContractSupplementGoodsInfoList);
        }

        return vo;
    }

    @Override
    public PurchContractSupplementInfo getLastPruchContractSupplementInfoByContractManagementId(Long id) {
        List<PurchContractSupplementInfo> purchContractSupplementInfos = lambdaQuery()
                .eq(PurchContractSupplementInfo::getPurchContractManagementId, id)
                .orderByDesc(PurchContractSupplementInfo::getGmtCreate)
                .list();

        PurchContractSupplementInfo supplementInfo = null;
        if (purchContractSupplementInfos != null && purchContractSupplementInfos.size() > 0) {
            supplementInfo = purchContractSupplementInfos.get(0);
        }

        return supplementInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkCallBack(Long businessKey) {
        PurchContractManagement purchContractManagement = purchContractService.getById(businessKey);
        PurchContractSupplementInfo supplementInfo = getLastPruchContractSupplementInfoByContractManagementId(purchContractManagement.getId());
        List<PurchContractSupplementElectronicInfo> purchContractSupplementElectronicInfos = purchContractSupplementElectronicInfoService.lambdaQuery().eq(PurchContractSupplementElectronicInfo::getcPurchContractSupplementInfoId, supplementInfo.getId()).list();
        if (CollectionUtil.isNotEmpty(purchContractSupplementElectronicInfos)) {
            for (PurchContractSupplementElectronicInfo purchContractSupplementElectronicInfo : purchContractSupplementElectronicInfos) {
                if (purchContractSupplementElectronicInfo.getCallBack().equals(0)) {
                    doSignChangeCallBackByQuery(purchContractSupplementElectronicInfo.getContractId(), true);
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startProcess(PurchContractChangeVo vo) {

        PurchContractManagement purchContractManagement = purchContractService.get(vo.getBusinessKey());

        if (purchContractManagement == null) {
            throw new ValidatorException(CodeUtil.FAIL, "对应采购管理信息不存在");
        }

        //状态为已完成时 开启变更流程
        if (ProjectInitiationStatusDict.ChildEnum.COMPLETED.getCode().equals(purchContractManagement.getContractStatus())) {
            purchContractService.startChangeProcess(purchContractManagement.getId());
            purchContractManagement.setContractStatus(ProjectInitiationStatusDict.ChildEnum.PROCESSING.getCode());
            purchContractService.updateById(purchContractManagement);
        }
    }


    @Override
    public void commitTask(PurchContractChangeVo vo) {
        PurchContractManagement contractManagement = purchContractService.getById(vo.getBusinessKey());

        BusinessProcessingLog lastLog = businessProcessingLogService
                .getByBusinessTypeBusinessKey(ConstantUtil.PURCH_CONTRACT_CHANGE_PROCESS, vo.getBusinessKey());
        if (lastLog == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到最新的日志信息！");
        }


        PurchContractSupplementInfo supplementInfo = vo.getContractSupplementInfo();
        if (vo.getContractSupplementInfo() == null || vo.getContractSupplementInfo().getSupplementContractNumber() == null) {
            throw new BusinessException(CodeUtil.PARAMETER_ERROR, "补充合同信息有误!");

        }

        //占用销售合同货物
        List<PurchContractSupplementGoodsInfo> goodsInfos = vo.getContractGoodsInfo();
        if (CollectionUtil.isNotEmpty(goodsInfos)){
            goodsInfos.forEach(goods->{
                if (goods.getSupplement()){
                    //补充货物
                    salesContractSupplementGoodsInfoService.lambdaUpdate()
                            .eq(SalesContractSupplementGoodsInfo::getId,goods.getSalesContractGoodsInfoId())
                            .set(SalesContractSupplementGoodsInfo::getOccupy,1).update();

                }else {
                    salesContractGoodsInfoService.lambdaUpdate()
                            .eq(CSalesContractGoodsInfo::getId,goods.getSalesContractGoodsInfoId())
                            .set(CSalesContractGoodsInfo::getOccupy,1).update();
                }
            });
        }


        String processKey = ConstantUtil.PURCH_CONTRACT_CHANGE_PROCESS;
        String assigneeKey = ConstantUtil.PURCH_CONTRACT_CHANGE_APPROVAL + ConstantUtil.CANDIDATE;

        //项目信息
        PurchContractBasicInfo purch = purchContractBasicInfoService.lambdaQuery()
                .eq(PurchContractBasicInfo::getPurchContractManagementId, contractManagement.getId()).one();

        List<Long> legalSpecialists = userService.findUserIdByRole(ConstantUtil.LEGAL_SPECIALIST);
        if (legalSpecialists == null || legalSpecialists.size() == 0) {
            throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.OPERATION_SPECIALIST + "角色内无任何用户！");
        }
        String listIds = legalSpecialists.stream().map(r -> String.valueOf(r)).collect(Collectors.joining(","));

        Map<String, Object> procVariables = new HashMap<>(1);
        procVariables.put(assigneeKey, listIds);
        Map<String, Object> msgVariables = new HashMap<>(2);
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, purch.getProjectName());
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                "业务编号为" + contractManagement.getBusinessNumber() + "”的项目已inOut“"
                        + ConstantConversionUtil.flowBusinessKeyNames.get(processKey) + "—formBusiness”阶段，");
        Long historyId = addHistory(supplementInfo);
        Boolean success = flowableService.completeMyTask(lastLog.getHistoricTaskId(), contractManagement, procVariables, null, historyId,
                msgVariables, processKey, legalSpecialists);
        if (success == null || !success) {
            throw new ValidatorException(CodeUtil.FAIL, "采购合同变更-业务录入时出错啦！");
        }
    }

    private Long addHistory(PurchContractSupplementInfo supplementInfo) {
        Long oldId = supplementInfo.getId();
        //保存补充信息
        PurchContractSupplementInfoHistory purchContractSupplementInfoHistory = new PurchContractSupplementInfoHistory();
        BeanUtils.copyProperties(supplementInfo, purchContractSupplementInfoHistory);
        purchContractSupplementInfoHistoryService.save(purchContractSupplementInfoHistory);
        //保存货物信息
        List<PurchContractSupplementGoodsInfo> purchContractSupplementGoodsInfoList = supplementGoodsInfoService.list(
                new QueryWrapper<PurchContractSupplementGoodsInfo>().eq("c_purch_contract_supplement_info_id", oldId)
        );
        if (purchContractSupplementGoodsInfoList != null && purchContractSupplementGoodsInfoList.size() > 0) {
            for (PurchContractSupplementGoodsInfo purchContractSupplementGoodsInfo : purchContractSupplementGoodsInfoList) {
                PurchContractSupplementGoodsInfoHistory purchContractSupplementGoodsInfoHistory = new PurchContractSupplementGoodsInfoHistory();
                BeanUtils.copyProperties(purchContractSupplementGoodsInfo, purchContractSupplementGoodsInfoHistory);
                purchContractSupplementGoodsInfoHistory.setPurchContractSupplementInfoId(purchContractSupplementInfoHistory.getId());
                purchContractSupplementGoodsInfoHistoryService.save(purchContractSupplementGoodsInfoHistory);
            }
        }
        //保存文件信息
//        AttachmentDto attachmentDto = AttachmentDto.builder()
//                .setEntityId(oldId)
//                .setChildEnum(FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_FILE)
//                .build();
//        List<FileStorage> fileStorages = sysAttachmentRefService.getFiles(attachmentDto);
//        if (CollectionUtil.isNotEmpty(fileStorages)) {
//            AttachmentDto attachmentDtoHistory = AttachmentDto.builder()
//                    .setEntityId(purchContractSupplementInfoHistory.getId())
//                    .setChildEnum(FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_HISTORY_FILE)
//                    .build();
//            sysAttachmentRefService.saveFileAndRefHis(fileStorages, attachmentDtoHistory);
//        }
        return purchContractSupplementInfoHistory.getId();
    }


    private PurchContractManagement getContractManageByBusinessKey(PurchContractChangeVo vo) {
        PurchContractManagement contractManagement = purchContractService.get(vo.getBusinessKey());
        if (contractManagement == null) {
            throw new BusinessException(CodeUtil.FAIL, "BusinessKey无效");
        }
        return contractManagement;
    }

    private void checkVo(PurchContractChangeVo vo) {
        if (vo == null || vo.getBusinessKey() == null) {
            throw new ValidatorException(CodeUtil.FAIL, "采购合同信息不能为空");
        }

        if (vo.getContractSupplementInfo() == null) {
            throw new ValidatorException(CodeUtil.FAIL, "采购合同变更补充信息不能为空");
        }

    }

    @Override
    public String getContractNumber(Long businessKey) {
        //合同编号，系统自动生成，生成规则为：
        List<PurchContractSupplementInfo> oldPurchContractSupplementInfos = lambdaQuery()
                .eq(PurchContractSupplementInfo::getPurchContractManagementId, businessKey)
                .orderByDesc(PurchContractSupplementInfo::getGmtCreate).list();
        PurchContractBasicInfo latestBasicInfo = purchContractBasicInfoService
                .getOne(new QueryWrapper<PurchContractBasicInfo>()
                        .eq("c_purch_contract_management_id", businessKey));
        if (latestBasicInfo == null) {
            throw new ValidatorException(CodeUtil.FAIL, "无法获取主合同信息！");
        }
        String contractNumber = latestBasicInfo.getContractNumber() + "-BO";
        if (CollectionUtil.isNotEmpty(oldPurchContractSupplementInfos)) {
            int number = (int) oldPurchContractSupplementInfos.stream().count() + 1;
            contractNumber = contractNumber + String.valueOf(number);
        } else {
            contractNumber = contractNumber + "1";
        }
        return contractNumber;
    }

    @Override
    public FileStorage makeContract(PurchContractSupplementApproval purchContractSupplementApproval) {

        if (CollectionUtil.isEmpty(purchContractSupplementApproval.getComments())){
            throw new BusinessException(CodeUtil.FAIL,"其他约定不能为空！");
        }

        List<PurchContractSupplementInfo> purchContractSupplementInfos = lambdaQuery()
                .eq(PurchContractSupplementInfo::getPurchContractManagementId, purchContractSupplementApproval.getBusinessKey())
                .orderByDesc(PurchContractSupplementInfo::getGmtCreate)
                .list();
        if (purchContractSupplementInfos == null || purchContractSupplementInfos.size() == 0) {
            throw new BusinessException(CodeUtil.FAIL, "未查到该变更信息");
        }
        //最新的变更信息
        PurchContractSupplementInfo supplementInfo = purchContractSupplementInfos.get(0);

        PurchContractManagement purchContractManagement = purchContractService.getById(supplementInfo.getPurchContractManagementId());
        PurchContractBasicInfo purchContractBasicInfo = purchContractBasicInfoService
                .lambdaQuery().eq(PurchContractBasicInfo::getPurchContractManagementId, supplementInfo.getPurchContractManagementId()).one();

        Platform platform = platformService.getById(purchContractBasicInfo.getTradingPlatformId());
        if (!platform.getAuthStatus().equals(1) || !platform.isAutoSignStatus()) {
            throw new ValidatorException(CodeUtil.FAIL, "贸易平台未认证或者未开启自动签署，无法制作合同！");
        }

        //制作合同
        File outFile = null;
        try {
            outFile = purchContractSupplementElectronicInfoService
                    .makePurchContractDocx(purchContractManagement, purchContractBasicInfo, platform, supplementInfo,purchContractSupplementApproval);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //将docx转为pdf
        String suffix = FileUtil.getSuffix(outFile.getName());
        String newPath = outFile.getAbsolutePath().replace(suffix, ".pdf");
        File purchContractPdfFile = OfficeConverterUtil.office2Pdf(outFile.getAbsolutePath(), newPath);
        FileStorage fileStorage = new FileStorage(purchContractPdfFile, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_FILE);
        fileStorageService.add(fileStorage);
        return fileStorage;
    }

}
