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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itextpdf.text.pdf.PdfReader;
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.dict.impl.SalesContractPersonTypeDict;
import com.sunxung.factoring.entity.customerinformation.ElectronicSignaturePersonal;
import com.sunxung.factoring.entity.electronicsignature.FddSignData;
import com.sunxung.factoring.entity.salescontractmanagement.*;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.entity.sys.FileStorageDO;
import com.sunxung.factoring.entity.sys.User;
import com.sunxung.factoring.mapper.salescontractmanagement.SalesContractApprovalMapper;
import com.sunxung.factoring.service.customerinformation.IElectronicSignaturePersonalService;
import com.sunxung.factoring.service.salescontractmanagement.*;
import com.sunxung.factoring.service.sys.FileService;
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 org.springframework.beans.BeanUtils;
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.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 销售合同审批service实现类
 * @Author : L.Jia
 * @Date: 2021-09-15 17:51
 */
@Service("sales_contract_approvalService")
public class SalesContractApprovalServiceImpl extends ServiceImpl<SalesContractApprovalMapper, SalesContractApproval>
        implements SalesContractApprovalService {

    @Autowired
    private SalesContractService salesContractService;
    @Autowired
    private FlowableService flowableService;
    @Autowired
    private IElectronicSignaturePersonalService electronicSignaturePersonalService;
    @Autowired
    private ISysAttachmentRefService sysAttachmentRefService;
    @Autowired
    private ISalesContractApprovalPersonInfoHistoryRefService salesContractApprovalPersonInfoHistoryRefService;
    @Autowired
    private FileStorageService fileStorageService;
    @Autowired
    private ICSalesContractBasicInfoService salesContractBasicInfoService;
    @Autowired
    private SalesContractRetentionInfoService salesContractRetentionInfoService;
    @Autowired
    private ICSalesSignConfirmationElectronicInfoService salesSignConfirmationElectronicInfoService;
    @Autowired
    private ICSalesSignConfirmationService salesSignConfirmationService;
    @Autowired
    private UserService userService;
    @Autowired
    private ISalesContractPersonInfoService salesContractPersonInfoService;
    @Autowired
    private FileService fileService;


    @Override
    public SalesContractApproval getView(Long id) {

        SalesContractApproval salesContractApproval = baseMapper.selectById(id);
        if (salesContractApproval == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应销售合同审批信息");
        }

        //填充质保金信息
        SalesContractRetentionInfo retentionInfo = salesContractRetentionInfoService.lambdaQuery().eq(SalesContractRetentionInfo::getSalesContractApprovalId, id).one();
        salesContractApproval.setRetentionInfo(retentionInfo);

        //文件
        AttachmentDto attachmentDto = AttachmentDto.builder()
                .setEntityId(id)
                .setChildEnum(FileModuleDict.ChildEnum.SALES_CONTRACT_APPROVAL_FILE)
                .build();
        List<FileStorage> files = sysAttachmentRefService.getFiles(attachmentDto);
        salesContractApproval.setFileStorages(files);

        //签署人信息
        List<SalesContractApprovalPersonInfoHistoryRef> personInfoHistoryRefs = salesContractApprovalPersonInfoHistoryRefService
                .lambdaQuery().eq(SalesContractApprovalPersonInfoHistoryRef::getSalesContractApprovalId, id).list();
        salesContractApproval.setPersonInfoHistoryRefList(personInfoHistoryRefs);


        return salesContractApproval;
    }

    @Override
    public SalesContractApproval getDetail(Long id) {

        SalesContractApproval contractApproval = new SalesContractApproval();

        CSalesContractBasicInfo contractBasicInfo = salesContractBasicInfoService
                .lambdaQuery().eq(CSalesContractBasicInfo::getcSalesContractManagementId, id).one();

        //质保金信息
        SalesContractRetentionInfo retentionInfo = new SalesContractRetentionInfo();
        retentionInfo.setRetention(contractBasicInfo.getRetention());
        retentionInfo.setRetentionPercent(contractBasicInfo.getRetentionPercent());
        contractApproval.setRetentionInfo(retentionInfo);

        //签署人信息
        List<CSalesContractPersonInfo> personInfos = salesContractPersonInfoService
                .lambdaQuery().eq(CSalesContractPersonInfo::getcSalesContractBasicInfoId, contractBasicInfo.getId()).list();
        List<SalesContractApprovalPersonInfoHistoryRef> personInfoHistoryRefs = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(personInfos)) {
            for (CSalesContractPersonInfo person : personInfos) {
                if (person.getType().equals(SalesContractPersonTypeDict.ChildEnum.SALESCONTRACTPERSONTYPE_SIGN.getCode())) {
                    SalesContractApprovalPersonInfoHistoryRef personHis = new SalesContractApprovalPersonInfoHistoryRef();
                    BeanUtils.copyProperties(person, personHis, "id");
                    personInfoHistoryRefs.add(personHis);
                }
            }
        }
        contractApproval.setPersonInfoHistoryRefList(personInfoHistoryRefs);

        //合同文件
        List<FileStorage> fileStorageList = new ArrayList<>();
        List<FileStorageDO> fileStorageDOS = fileService.findByBusinessId(contractBasicInfo.getId(),
                FileModuleDict.ChildEnum.SALES_CONTRACT_FILE.getCode());
        if (CollectionUtil.isNotEmpty(fileStorageDOS)) {
            fileStorageDOS.forEach(fileStorageDO -> {
                FileStorage fileStorage = new FileStorage();
                BeanUtils.copyProperties(fileStorageDO, fileStorage, "id");
                fileStorage.setFileType(fileStorageDO.getType());
                fileStorage.setAbsolutePath(fileStorageDO.getAbsolutePath());
                fileStorage.setOriginalName(fileStorageDO.getOriginalName());
                fileStorage.setName(fileStorageDO.getOriginalName());
                fileStorage.setPath(fileStorageDO.getPath());
                fileStorageService.add(fileStorage);
                fileStorageList.add(fileStorage);
            });
        }
        contractApproval.setFileStorages(fileStorageList);

        //是否有履约保证金
        contractApproval.setPerformanceBond(contractBasicInfo.getPerformanceBond());

        return contractApproval;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void audit(SalesContractApproval salesContractApproval) {

        if (salesContractApproval == null || salesContractApproval.getBusinessKey() == null) {
            throw new ValidatorException(CodeUtil.FAIL, "审核信息或者业务id不能为空");
        }
        SalesContractRetentionInfo retentionInfo = salesContractApproval.getRetentionInfo();
        if (salesContractApproval.getApprovalConclusion().equals("pass") && retentionInfo == null) {
            throw new ValidatorException(CodeUtil.FAIL, "质保金信息不能为空！");
        }

        CSalesContract contractManagement = salesContractService.getById(salesContractApproval.getBusinessKey());
        if (contractManagement == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应销售合同管理信息");
        }

        CSalesContractBasicInfo salesContractBasicInfo = salesContractBasicInfoService.getOne(new QueryWrapper<CSalesContractBasicInfo>()
                .eq("c_sales_contract_management_id", salesContractApproval.getBusinessKey())
                .orderByDesc("gmt_create").last("limit 1"));

        if (salesContractBasicInfo == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应销售合同信息");
        }

        salesContractApproval.setAuditorId(ThreadLocalUtil.getUserId());
        salesContractApproval.setcSalesContractBasicInfoId(salesContractBasicInfo.getId());
        baseMapper.insert(salesContractApproval);

        //质保金
        if (retentionInfo != null) {
            retentionInfo.setSalesContractApprovalId(salesContractApproval.getId());
            retentionInfo.setRetention(salesContractBasicInfo.getRetention());
            salesContractRetentionInfoService.save(retentionInfo);
        }

        //电子签信息
        CSalesSignConfirmation signConfirmation = new CSalesSignConfirmation();
        ElectronicSignaturePersonal signaturePersonal = new ElectronicSignaturePersonal();
        List<CSalesSignConfirmationElectronicInfo> signConfirmationElectronicInfos = new ArrayList<>();

        if (salesContractApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_PASS) && salesContractApproval.getSignConfirm() == 1) {

            //保存文件信息
            AttachmentDto attachmentDto = AttachmentDto.builder()
                    .setEntityId(salesContractApproval.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.SALES_CONTRACT_APPROVAL_FILE)
                    .build();
            List<Long> fileIds = salesContractApproval.getFileIds();
            if (CollectionUtil.isNotEmpty(fileIds)) {
                sysAttachmentRefService.saveRef(fileIds, attachmentDto);
            }

            if (CollectionUtil.isEmpty(salesContractApproval.getPersonInfoHistoryRefList())) {
                throw new ValidatorException(CodeUtil.FAIL, "合同签署人必须选择一个！");
            }
            SalesContractApprovalPersonInfoHistoryRef personInfoHistoryRef = salesContractApproval.getPersonInfoHistoryRefList().get(0);
            if (StringUtil.isEmpty(personInfoHistoryRef.getName()) || StringUtil.isEmpty(personInfoHistoryRef.getMobile())) {
                throw new ValidatorException(CodeUtil.FAIL, "签署人信息必须全填！");
            }
            List<ElectronicSignaturePersonal> oldElectronicSignaturePersonals = electronicSignaturePersonalService.lambdaQuery()
                    .eq(ElectronicSignaturePersonal::getName, personInfoHistoryRef.getName())
                    .eq(ElectronicSignaturePersonal::getMobile, personInfoHistoryRef.getMobile()).list();
            ElectronicSignaturePersonal oldElectronicSignaturePersonal = null;
            if (CollectionUtil.isNotEmpty(oldElectronicSignaturePersonals)) {
                if (oldElectronicSignaturePersonals.size() > 1) {
                    oldElectronicSignaturePersonals = oldElectronicSignaturePersonals.stream()
                            .filter(person -> person.getSocialCreditCode() != null).collect(Collectors.toList());

                }
                oldElectronicSignaturePersonal = oldElectronicSignaturePersonals.get(0);
            }

            if (oldElectronicSignaturePersonal != null) {
                signaturePersonal = oldElectronicSignaturePersonal;
            } else {
                ElectronicSignaturePersonal electronicSignaturePersonal = new ElectronicSignaturePersonal();
                BeanUtils.copyProperties(personInfoHistoryRef, electronicSignaturePersonal, "id");
                electronicSignaturePersonal.setAuthStatus(0);
                electronicSignaturePersonalService.save(electronicSignaturePersonal);
                //Update用来生成链接
                electronicSignaturePersonalService.updateInfo(electronicSignaturePersonal);
                signaturePersonal = electronicSignaturePersonal;
            }

            personInfoHistoryRef.setSalesContractApprovalId(salesContractApproval.getId());
            salesContractApprovalPersonInfoHistoryRefService.save(personInfoHistoryRef);

            //销售合同流程
            List<FileStorage> files = sysAttachmentRefService.getFiles(attachmentDto);
            if (CollectionUtil.isEmpty(files)) {
                throw new ValidatorException(CodeUtil.FAIL, "签署文件为空");
            }
            signConfirmation.setcSalesContractManagementId(contractManagement.getId());
            salesSignConfirmationService.save(signConfirmation);

            //保存文件信息
            AttachmentDto attachmentDtoSign = AttachmentDto.builder()
                    .setEntityId(signConfirmation.getId())
                    .setChildEnum(FileModuleDict.ChildEnum.SIGN_CONFIRM_FILE)
                    .build();

            sysAttachmentRefService.saveRef(fileIds, attachmentDtoSign);

            for (FileStorage fileStorage : files) {
                CSalesSignConfirmationElectronicInfo signConfirmationElectronicInfo = new CSalesSignConfirmationElectronicInfo();

                signConfirmationElectronicInfo.setcSalesSignConfirmationId(signConfirmation.getId());
                signConfirmationElectronicInfo.setContractName(fileStorage.getOriginalName());
                signConfirmationElectronicInfo.setFileId(fileStorage.getId());
                signConfirmationElectronicInfo.setElectronicSignaturePersonalId(signaturePersonal.getId());
                signConfirmationElectronicInfo.setSignStatus(0);
                salesSignConfirmationElectronicInfoService.save(signConfirmationElectronicInfo);
                signConfirmationElectronicInfos.add(signConfirmationElectronicInfo);
            }
        }

        //流程处理
        String processKey = ConstantUtil.SALES_CONTRACT;
        String assigneeKey = ConstantUtil.SIGN_CONFIRMATION_APPROVAL + ConstantUtil.ASSIGNEE;

        Map<String, Object> procVariables = new HashMap<>(1);
        User admin = userService.getByLoginName("admin");
        procVariables.put(assigneeKey, admin.getId());
        String result;
        if (salesContractApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_BACK)) {
            result = ConstantConversionUtil.APPROVAL_RESULT_BACK_DISPLAY;
        } else {
            if (salesContractApproval.getSignConfirm() == 1) {
                result = ConstantConversionUtil.APPROVAL_RESULT_SIGN_DISPLAY;
            } else {
                result = ConstantConversionUtil.APPROVAL_RESULT_NO_SIGN_DISPLAY;
                contractManagement.setContractStatus(ProjectInitiationStatusDict.ChildEnum.COMPLETED.getCode());
                salesContractService.updateById(contractManagement);
            }
        }
        Map<String, Object> msgVariables = new HashMap<>(2);
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, contractManagement.getBusinessNumber());
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                "业务编号为" + contractManagement.getBusinessNumber() + "”的项目已inOut“"
                        + ConstantConversionUtil.flowBusinessKeyNames.get(processKey) + "—formBusiness”阶段，");
        Boolean success = flowableService.completeMyTask(salesContractApproval.getTaskId(), contractManagement, procVariables,
                result,
                salesContractApproval.getId(), msgVariables, processKey);
        if (success == null || !success) {
            throw new ValidatorException(CodeUtil.FAIL, "销售合同审批出错啦！");
        }

        if (result.equals(ConstantConversionUtil.APPROVAL_RESULT_SIGN_DISPLAY)) {
            uploadContract(signaturePersonal, signConfirmation, signConfirmationElectronicInfos);
        }

    }

    @Override
    public CSalesSignConfirmation uploadContract(ElectronicSignaturePersonal electronicSignaturePersonal, CSalesSignConfirmation salesSignConfirmation,
                                                 List<CSalesSignConfirmationElectronicInfo> signElectronicInfos) {
        if (electronicSignaturePersonal.getAuthStatus().equals(1)) {
            List<FddSignData> fddSignDataList = new ArrayList();
            if (com.github.pagehelper.util.StringUtil.isEmpty(salesSignConfirmation.getContractLink())) {
                for (CSalesSignConfirmationElectronicInfo signConfirmationElectronicInfo : signElectronicInfos) {
                    if (signConfirmationElectronicInfo.getSignStatus() == 0) {
                        //将文件转换为PDF在上传法大大
                        FileStorage fileStorage = fileStorageService.get(signConfirmationElectronicInfo.getFileId());
                        File file = new File(fileStorage.getAbsolutePath());
                        String fileType = fileStorage.getFileType();
                        String newPath = file.getAbsolutePath().replace(fileType, ".pdf");
                        File pdfFile;
                        //只支持图片和excel转换
                        if (fileType.equals(".pdf")) {
                            pdfFile = file;
                        } else if (fileType.equals(".xlsx") || fileType.equals(".xls")) {
                            pdfFile = OfficeConverterUtil.office2Pdf(file.getAbsolutePath(), newPath);
                        } else if (fileType.equals(".jpg") || fileType.equals(".png") || fileType.equals(".jpeg") || fileType.equals(".bmp")) {
                            PdfUtil.convert(file.getAbsolutePath(), newPath);
                            pdfFile = new File(newPath);
                        } else {
                            throw new ValidatorException(CodeUtil.FAIL, "文件类型错误！");
                        }
                        PdfReader pdfReader = null;
                        try {
                            pdfReader = new PdfReader(new FileInputStream(pdfFile));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        int pages = pdfReader.getNumberOfPages();
                        //上传合同
                        String contractId = UUID.randomUUID().toString().trim().replaceAll("-", "").toUpperCase();
                        String docTitle = fileStorage.getOriginalName();
                        String transactionId = UUID.randomUUID().toString().trim().replaceAll("-", "").toUpperCase();
                        ElectronicSignatureUtil.uploadContract(contractId, docTitle, pdfFile);
                        //批量手动签署
                        FddSignData fddSignData = new FddSignData();
                        fddSignData.setContractId(contractId);
                        fddSignData.setContractType("sales");
                        String page = String.valueOf(pages - 1);
                        fddSignData.setSearchLocation(page);
                        fddSignData.setTransactionId(transactionId);
                        fddSignDataList.add(fddSignData);

                        signConfirmationElectronicInfo.setContractId(contractId);
                        signConfirmationElectronicInfo.setTransactionId(transactionId);
                        salesSignConfirmationElectronicInfoService.updateById(signConfirmationElectronicInfo);
                    }
                }
                if (CollectionUtil.isNotEmpty(fddSignDataList)) {
                    String contractLink = ElectronicSignatureUtil.batchSignUrlSearchLocation(electronicSignaturePersonal.getFddCustomerId(), fddSignDataList, "签署确认批量签署");
                    //合同链接
                    String shortUrl = ElectronicSignatureUtil.shortUrl(null, contractLink);
                    salesSignConfirmation.setContractLink(contractLink);
                    salesSignConfirmation.setShortContractLink(shortUrl);
                    salesSignConfirmation.setShortContractLinkCreate(new Date());
                    salesSignConfirmationService.updateById(salesSignConfirmation);
                }

            }
        }
        return salesSignConfirmation;
    }

}
