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

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.dict.impl.FileModuleDict;
import com.sunxung.factoring.entity.electronicsignature.FddSignData;
import com.sunxung.factoring.entity.entprise.Enterprise;
import com.sunxung.factoring.entity.project.BusinessProcessingLog;
import com.sunxung.factoring.entity.purchcontractmanagement.*;
import com.sunxung.factoring.entity.supplier.SupplierInfo;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.entity.tradingPlatform.Platform;
import com.sunxung.factoring.mapper.purchcontractmanagement.PurchSupplementContractSignConclusionMapper;
import com.sunxung.factoring.service.entprise.IEnterpriseService;
import com.sunxung.factoring.service.project.BusinessAssigneeService;
import com.sunxung.factoring.service.project.BusinessProcessingLogService;
import com.sunxung.factoring.service.purchcontractmanagement.*;
import com.sunxung.factoring.service.supplier.ISupplierInfoService;
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.dto.AttachmentDto;
import com.sunxung.factoring.service.sys.flowable.FlowableService;
import com.sunxung.factoring.service.tradingPlatform.PlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 采购合同 合同的签署结论 服务实现类
 * </p>
 *
 * @author liutao
 * @since 2023-03-28
 */
@Service("purch_contract_change_sign_confirmService")
public class PurchSupplementContractSignConclusionServiceImpl extends ServiceImpl<PurchSupplementContractSignConclusionMapper, PurchSupplementContractSignConclusion> implements IPurchSupplementContractSignConclusionService {

    @Autowired
    private UserService userService;

    @Autowired
    private BusinessAssigneeService assigneeService;

    @Autowired
    private IPurchContractSupplementElectronicInfoService purchContractSupplementElectronicInfoService;

    @Autowired
    private PurchContractService purchContractService;

    @Autowired
    private IPurchContractSupplementInfoService supplementInfoService;

    @Autowired
    private BusinessProcessingLogService businessProcessingLogService;

    @Autowired
    private FlowableService flowableService;

    @Autowired
    private DictionaryService dictService;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private IPurchContractSupplementApprovalService purchContractSupplementApprovalService;

    @Autowired
    private ISysAttachmentRefService sysAttachmentRefService;

    @Autowired
    private PurchContractBasicInfoService purchContractBasicInfoService;

    @Autowired
    private IPurchSupplementContractSignConclusionService purchSupplementContractSignConclusionService;

    @Autowired
    private ISupplierInfoService supplierInfoService;

    @Autowired
    private IEnterpriseService enterpriseService;

    @Autowired
    private IUploadPurchSupplementContractService uploadPurchSupplementContractService;

    @Autowired
    private PlatformService platformService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sign(PurchSupplementContractSignConclusion purchSupplementContractSignConclusion) throws IOException {

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

        Long businessKey = purchSupplementContractSignConclusion.getBusinessKey();
        PurchContractSupplementInfo lastPruchContractSupplementInfoByContractManagementId = supplementInfoService
                .lambdaQuery().eq(PurchContractSupplementInfo::getPurchContractManagementId, businessKey)
                .orderByDesc(PurchContractSupplementInfo::getGmtCreate).last("limit 1").one();
        if (lastPruchContractSupplementInfoByContractManagementId == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应采购合同补充信息");
        }
        PurchContractManagement purchContractManagement = purchContractService.getById(businessKey);

        //获取合同对应的最新签署信息
        List<PurchContractSupplementElectronicInfo> purchContractSupplementElectronicInfos = purchContractSupplementElectronicInfoService.lambdaQuery().eq(PurchContractSupplementElectronicInfo::getcPurchContractSupplementInfoId, lastPruchContractSupplementInfoByContractManagementId.getId()).list();

        boolean allMatch = purchContractSupplementElectronicInfos.stream().allMatch(r -> r.getSignStatus());
        if (!allMatch) {
            throw new ValidatorException(CodeUtil.FAIL, "所有合同必须全部签署完成才能提交！");
        }
        //保存签署确认信息
        purchSupplementContractSignConclusion.setPurchContractSupplementInfoId(lastPruchContractSupplementInfoByContractManagementId.getId());
        saveOrUpdate(purchSupplementContractSignConclusion);


        //走变更流程
        String processKey = ConstantUtil.PURCH_CONTRACT_CHANGE_PROCESS;
        String assigneeKey = ConstantUtil.PURCH_CONTRACT_CHANGE_FINAL_APPROVAL + ConstantUtil.CANDIDATE;


        BusinessProcessingLog log = businessProcessingLogService.getByBusinessTypeBusinessKey(ConstantUtil.PURCH_CONTRACT_CHANGE_PROCESS, businessKey);
        if (log == null) {
            throw new BusinessException(CodeUtil.FAIL, "日志信息为空！");
        }
        List<Long> legalSpecialists = userService.findUserIdByRole(ConstantUtil.LEGAL_SPECIALIST);
        if (legalSpecialists == null || legalSpecialists.size() == 0) {
            throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.OPERATION_SPECIALIST + "角色内无任何用户！");
        }
        String legals = legalSpecialists.stream().map(c -> c.toString()).collect(Collectors.joining(","));
        Map<String, Object> procVariables = new HashMap<>(1);
        procVariables.put(assigneeKey, legals);
        String result = null;
        if (purchSupplementContractSignConclusion.getConclusion().equals("pass")) {
            result = "线上";
        }
        procVariables.put("result", result);

        Map<String, Object> msgVariables = new HashMap<>(2);

        PurchContractBasicInfo contractBasicInfo = purchContractBasicInfoService
                .lambdaQuery().eq(PurchContractBasicInfo::getPurchContractManagementId, purchContractManagement.getId()).one();
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, contractBasicInfo.getProjectName());
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                "业务编号为" + purchContractManagement.getBusinessNumber() + "”的项目已inOut“"
                        + ConstantConversionUtil.flowBusinessKeyNames.get(processKey) + "—formBusiness”阶段，");
        Boolean success = flowableService.completeMyTask(log.getHistoricTaskId(), purchContractManagement, procVariables,
                null,
                purchSupplementContractSignConclusion.getId(), msgVariables, processKey, legalSpecialists);
        if (success == null || !success) {
            throw new ValidatorException(CodeUtil.FAIL, "采购合同签署出错啦！");
        }

    }

    @Override
    public PurchSupplementContractSignConclusion getView(Long id) {
        PurchSupplementContractSignConclusion purchSupplementContractSignConclusion = getById(id);

        //供应商信息
        PurchContractSupplementInfo supplementInfo = supplementInfoService.lambdaQuery()
                .eq(PurchContractSupplementInfo::getId, purchSupplementContractSignConclusion.getPurchContractSupplementInfoId()).one();
        PurchContractManagement purchContractManagement = purchContractService.getById(supplementInfo.getPurchContractManagementId());
        SupplierInfo supplierInfo = supplierInfoService.get(purchContractManagement.getSupplierId());
        Enterprise supplier = enterpriseService.getById(supplierInfo.getcEnterpriseId());
        purchSupplementContractSignConclusion.setSupplierInfo(supplier);

        AttachmentDto attachmentDto = AttachmentDto.builder()
                .setEntityId(supplementInfo.getId())
                .setChildEnum(FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_SIGN_FILE)
                .build();
        //已签署文件
        List<FileStorage> files = sysAttachmentRefService.getFiles(attachmentDto);
        purchSupplementContractSignConclusion.setFiles(files);

        //采购合同变更电子签信息
        List<PurchContractSupplementElectronicInfo> supplementElectronicInfoList = purchContractSupplementElectronicInfoService
                .lambdaQuery().eq(PurchContractSupplementElectronicInfo::getcPurchContractSupplementInfoId, purchSupplementContractSignConclusion.getPurchContractSupplementInfoId()).list();
        purchSupplementContractSignConclusion.setPurchContractElectronicInfos(supplementElectronicInfoList);



        return purchSupplementContractSignConclusion;
    }

    @Override
    public PurchSupplementContractSignConclusion getDetail(Long businessKey) {

        PurchContractManagement contractManagement = purchContractService.getById(businessKey);

        PurchContractBasicInfo basicInfo = purchContractBasicInfoService.lambdaQuery().eq(PurchContractBasicInfo::getPurchContractManagementId, businessKey).one();

        PurchContractSupplementInfo lastSupplement = supplementInfoService
                .lambdaQuery().eq(PurchContractSupplementInfo::getPurchContractManagementId, businessKey)
                .orderByDesc(PurchContractSupplementInfo::getGmtCreate).last("limit 1").one();

        PurchSupplementContractSignConclusion purchSupplementContractSignConclusion = purchSupplementContractSignConclusionService
                .lambdaQuery().eq(PurchSupplementContractSignConclusion::getPurchContractSupplementInfoId, lastSupplement.getId()).one();

        Platform platform = platformService.getById(contractManagement.getTradingPlatformId());

        SupplierInfo supplierInfo = supplierInfoService.get(contractManagement.getSupplierId());
        Enterprise supplier = enterpriseService.getById(supplierInfo.getcEnterpriseId());

        if (purchSupplementContractSignConclusion == null) {
            purchSupplementContractSignConclusion = new PurchSupplementContractSignConclusion();
        }

        List<PurchContractSupplementElectronicInfo> electronicInfos = purchContractSupplementElectronicInfoService
                .lambdaQuery().eq(PurchContractSupplementElectronicInfo::getcPurchContractSupplementInfoId, lastSupplement.getId())
                .list();
        if (CollectionUtil.isEmpty(electronicInfos)) {
            electronicInfos = new ArrayList<>();
            PurchContractSupplementApproval supplementApproval = purchContractSupplementApprovalService
                    .lambdaQuery().eq(PurchContractSupplementApproval::getPurchContractSupplementInfoId, lastSupplement.getId())
                    .orderByDesc(PurchContractSupplementApproval::getGmtCreate).last("limit 1").one();
            //批量手动签署
            List<FddSignData> fddSignDataList = new ArrayList<FddSignData>();

                //之前制作好的待处理文件
                AttachmentDto attachmentDto = AttachmentDto.builder()
                        .setEntityId(supplementApproval.getId())
                        .setChildEnum(FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SUPPLEMENT_MAKE_FILE)
                        .build();
                //只有一个文件
                List<FileStorage> files = sysAttachmentRefService.getFiles(attachmentDto);
                FileStorage fileStorage;
                if (CollectionUtil.isNotEmpty(files)) {
                    fileStorage = files.get(0);
                } else {
                    throw new ValidatorException(CodeUtil.FAIL, "未查询到文件！");
                }
                String filePath = fileStorage.getAbsolutePath();
                File purchContractPdfFile = new File(filePath);
                String name = lastSupplement.getSupplementContractNumber() + "-" + basicInfo.getContractName();
                doAutoSign(basicInfo, lastSupplement, supplier, electronicInfos, purchContractPdfFile,
                        fddSignDataList, name,platform);

            //上传的合同
            if (supplementApproval != null && supplementApproval.getUpload().equals(1)) {
                List<UploadPurchSupplementContract> uploadPurchContracts = uploadPurchSupplementContractService
                        .lambdaQuery().eq(UploadPurchSupplementContract::getPurchContractSupplementApprovalId, supplementApproval.getId()).list();
                for (UploadPurchSupplementContract uploadPurchContract : uploadPurchContracts) {
                    AttachmentDto attachmentDtoUpload = AttachmentDto.builder()
                            .setEntityId(uploadPurchContract.getId())
                            .setChildEnum(FileModuleDict.ChildEnum.PURCHASE_SUPPLEMENT_CONTRACT_UPLOAD_CONTRACT_FILE)
                            .build();
                    //只有一个文件
                    List<FileStorage> fileStorages = sysAttachmentRefService.getFiles(attachmentDtoUpload);
                    FileStorage uploadFileStorage;
                    if (CollectionUtil.isNotEmpty(fileStorages)) {
                        uploadFileStorage = fileStorages.get(0);
                    } else {
                        throw new ValidatorException(CodeUtil.FAIL, "未查询到文件！");
                    }
                    File uploadPdf = new File(uploadFileStorage.getAbsolutePath());
                    doAutoSign(basicInfo, lastSupplement, supplier, electronicInfos, uploadPdf,
                            fddSignDataList, lastSupplement.getSupplementContractNumber() + "-" + uploadPurchContract.getContractName(),
                            platform);
                }
            }
            String contractLink = ElectronicSignatureUtil.manualBatchSign(supplier.getFddCustomerId(), fddSignDataList, basicInfo.getContractName());
            String shortUrl = ElectronicSignatureUtil.shortUrl(null, contractLink);
            for (PurchContractSupplementElectronicInfo supplementElectronicInfo : electronicInfos) {
                supplementElectronicInfo.setShortContractLink(shortUrl);
                supplementElectronicInfo.setContractLink(contractLink);
                purchContractSupplementElectronicInfoService.saveOrUpdate(supplementElectronicInfo);
            }
        }

        purchSupplementContractSignConclusion.setPurchContractElectronicInfos(electronicInfos);

        PurchContractManagement purchContractManagement = purchContractService.getById(businessKey);

        purchSupplementContractSignConclusion.setSupplierInfo(supplier);

        return purchSupplementContractSignConclusion;
    }

    private void doAutoSign(PurchContractBasicInfo purch, PurchContractSupplementInfo supplementInfo, Enterprise supplier,
                            List<PurchContractSupplementElectronicInfo> electronicInfos, File purchContractPdfFile,
                            List<FddSignData> fddSignDataList, String contractName,Platform platform) {

        //上传合同
        String contractId = UUID.randomUUID().toString().trim().replaceAll("-", "").toUpperCase();
        purch.setContractId(contractId);
        purchContractBasicInfoService.updateById(purch);
        //采购合同自动签署
        String transactionIdAuto = UUID.randomUUID().toString().trim().replaceAll("-", "").toUpperCase();
        ElectronicSignatureUtil.uploadContract(contractId, contractName, purchContractPdfFile);
        String signKeyword = "xf";
        ElectronicSignatureUtil.autoSign(transactionIdAuto, contractId, platform.getFddCustomerId(), contractName, signKeyword);

        FddSignData fddSignData = new FddSignData();
        fddSignData.setContractId(contractId);
        fddSignData.setContractType("Purch");
        fddSignData.setSignKeyword("gys");
        String transactionId = UUID.randomUUID().toString().trim().replaceAll("-", "").toUpperCase();
        while (transactionId.contains("FDD")) {
            transactionId = UUID.randomUUID().toString().trim().replaceAll("-", "").toUpperCase();
        }
//        transactionIdCache.saveObjBuildTransactionId(transactionId,"SIGNPURCHFDD" + purchContractManagement.getId() + "FDD" + purch.getId() + "FDD" + taskId + "FDD" + ThreadLocalUtil.getUserId());
        fddSignData.setTransactionId(transactionId);
        fddSignDataList.add(fddSignData);

        PurchContractSupplementElectronicInfo electronicInfo = new PurchContractSupplementElectronicInfo();
        electronicInfo.setSignStatus(false);
        electronicInfo.setCertifyStatus(false);
        electronicInfo.setContractId(contractId);
        electronicInfo.setTransactionId(transactionId);
        electronicInfo.setShortContractLinkCreate(new Date());
        electronicInfo.setCertifyLink(supplier.getShortAuthUrl());
        electronicInfo.setFddCustomerId(supplier.getFddCustomerId());
        //认证状态
        electronicInfo.setCertifyStatus(supplier.getAuthStatus());
        electronicInfo.setContractName(contractName);
        electronicInfo.setcPurchContractSupplementInfoId(supplementInfo.getId());
        electronicInfos.add(electronicInfo);
    }


}
