package com.trade.client.trade.salescontract.service.impl;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.bean.BeanUtil;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.trade.client.enterprise.customer.service.EnterpriseService;
import com.trade.client.trade.purchasecontract.service.PurchaseContractService;
import com.trade.client.trade.salescontract.dto.SalesUploadContractDto;
import com.trade.common.exception.ServiceException;
import com.trade.common.utils.ConstantUtil;
import com.trade.common.utils.LoggerUtil;
import com.trade.common.utils.StringUtils;
import com.trade.common.utils.file.ExcelImportUtils;
import com.trade.common.utils.file.FileDownUtils;
import com.trade.common.utils.file.FileUtils;
import com.trade.service.DictConstants;
import com.trade.service.contract.service.ISFileTemplateService;
import com.trade.service.enterprise.companyrelated.domain.ImporterEntity;
import com.trade.service.enterprise.companyrelated.domain.VendorEntity;
import com.trade.service.enterprise.companyrelated.service.IImporterEntityService;
import com.trade.service.enterprise.companyrelated.service.IVendorEntityService;
import com.trade.service.enterprise.customer.domain.Enterprise;
import com.trade.service.enterprise.customer.domain.EnterpriseRelatedPerson;
import com.trade.service.enterprise.customer.dto.EnterpriseDto;
import com.trade.service.enterprise.customer.service.EnterpriseBaseService;
import com.trade.service.enterprise.customer.service.EnterpriseRelatedPersonBaseService;
import com.trade.service.filestorage.service.OSSFileService;
import com.trade.service.filestorage.service.TFileStorageService;
import com.trade.service.filestorage.util.oss.OSSUtil;
import com.trade.service.system.service.ISysDictDataService;
import com.trade.service.trade.salescontract.domain.*;
import com.trade.service.trade.salescontract.dto.*;
import com.trade.service.trade.salescontract.service.*;
import com.trade.service.trade.salescontract.vo.ImportCommodityVo;
import com.trade.service.serialNum.service.SerialNumberGenerator;
import com.trade.service.trade.salesorder.constant.SaleOrderConstant;
import com.trade.service.tradingplatform.domain.TradingPlatform;
import com.trade.service.tradingplatform.service.TradingPlatformBaseService;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.trade.client.enterprise.customer.domain.CustomerUser;
import com.trade.client.enterprise.customer.service.CustomerUserService;
import com.trade.client.trade.salescontract.dto.SalesContractInfoDto;
import com.trade.client.trade.salescontract.service.SalesService;
import com.trade.common.constant.HttpStatus;
import com.trade.common.core.page.GridPage;
import com.trade.common.enums.ContractStatus;
import com.trade.common.enums.SubmitStatus;
import com.trade.common.exception.ValidatorException;
import com.trade.common.validate.ValidatorGroup;
import com.trade.common.validate.ValidatorUtil;
import com.trade.service.filestorage.enums.FileTypeEnum;
import com.trade.service.contract.dto.ContractGenInputItem;
import com.trade.service.contract.dto.ContractGenOutputItem;
import com.trade.service.contract.service.ContractService;
import com.trade.service.filestorage.entity.TFileStorage;
import com.trade.service.filestorage.enums.FileModuleEnum;
import com.trade.service.filestorage.util.MultipartFileUtil;
import com.trade.service.trade.salescontract.service.impl.SalesDataConverter;
import com.trade.service.trade.salescontract.vo.SalesContractInfoVo;
import com.trade.service.trade.salescontract.vo.SalesContractVo;

import cn.hutool.core.collection.CollectionUtil;

/**
 * @description: 销售服务实现类
 * @Author: wanglang
 * @Date: 2024/9/3 19:14
 * @Version: 1.0
 */
@Service
public class SalesServiceImpl implements SalesService {

    private static final Logger log = LoggerUtil.logger(LoggerUtil.LogFileNameEnum.SERVICES_LOG);
    ;
    @Resource
    private CustomerUserService customerUserService;
    @Resource
    private SalesContractService salesContractService;
    @Resource
    private SalesDataConverter salesDataConverter;
    @Resource
    private ContractFileService contractFileService;
    @Resource
    private OSSFileService ossFileService;
    @Resource
    private TFileStorageService tFileStorageService;
    @Resource
    private OSSUtil ossUtil;
    @Resource
    private ContractService contractService;
    @Resource
    private SalesCommodityService salesCommodityService;
    @Resource
    private ContractTermsService contractTermsService;
    @Resource
    private ContractTermsExtendService contractTermsExtendService;
    @Resource
    private IVendorEntityService iVendorEntityService;
    @Resource
    private SerialNumberGenerator serialNumberGenerator;
    @Resource
    private EnterpriseService enterpriseService;
    @Resource
    private PurchaseContractService purchaseContractService;
    @Value("${templates.path}")
    private String path;
    @Resource
    private ISFileTemplateService fileTemplateService;
    @Resource
    private EnterpriseRelatedPersonBaseService relatedPersonBaseService;
    @Resource
    private TradingPlatformBaseService tradingPlatformBaseService;
    @Resource
    private IImporterEntityService IImporterEntityService;
    @Resource
    private ISysDictDataService iSysDictDataService;
    @Resource
    private EnterpriseBaseService enterpriseBaseService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveSalesContract(SalesContractInfoDto salesContractInfoDto, HttpServletRequest request) {
        CustomerUser customerUser = customerUserService.getCustomerUser();
        SalesContractDto salesContractDto = salesContractInfoDto.getSalesContract();
        salesContractInfoDto.getSalesContract().setCustomerUserId(customerUser.getId());
        preVerification(salesContractInfoDto);
        // MultipartFile transferFile = null;
        // if (request instanceof MultipartHttpServletRequest) {
        // transferFile = ((MultipartHttpServletRequest) request).getFile("file");
        // }
        // 设置为草稿状态
        // salesContractDto.setSubmitStatus(SubmitStatus.DRAFT.getCode());
        SalesContract contractNoExist = null;
        if (salesContractDto.getId() != null) {
            contractNoExist = salesContractService.getById(salesContractDto.getId());
        }
        // SalesContract contractNoExist = salesContractService.lambdaQuery()
        // .eq(SalesContract::getContractNo, salesContractDto.getContractNo()).eq(SalesContract::getDeleted, 0)
        // .one();
        // checkSalesContractParameter(salesContractDto, transferFile, contractNoExist);
        if (!SubmitStatus.DRAFT.getCode().equals(salesContractDto.getSubmitStatus())) {
            if (!salesContractDto.getTemplateType() && salesContractDto.getFileId() == null) {
                throw new ValidatorException(HttpStatus.ERROR, "请您上传合同！");
            }
        }
        if (contractNoExist != null && SubmitStatus.FORMAL.getCode().equals(contractNoExist.getSubmitStatus())) {
            throw new ValidatorException(HttpStatus.ERROR, "该合同编号已存在正式合同，请勿重复提交！");
        }
        boolean isTemplate = false;
        ContractFile contractFile = handleContractFile(salesContractDto, customerUser, null, isTemplate);
        if (contractFile != null) {
            salesContractDto.setContractNo(contractFile.getContractNo());
        }
        salesContractDto.setContractStatus(ContractStatus.DRAFT.getCode());
        SalesContract salesContract = salesDataConverter.convertSalesContractDo(salesContractDto);
        salesContract.setCustomerUserId(customerUser.getId());
        // 更新时 这个字段不能为空
        if (salesContract.getId() != null) {
            salesContract.setUpdateBy(customerUser.getNickname());
            salesContractService.updateById(salesContract);
            saveContractFile(salesContractDto, contractFile);
        } else {
            // 1、保存合同信息
            salesContract.setCreateBy(customerUser.getNickname());
            salesContractService.save(salesContract);
            saveContractFile(salesContractDto, contractFile);
        }
        // 3、保存商品信息
        List<SalesCommodity> salesCommodities = salesCommodityService.lambdaQuery()
                .eq(SalesCommodity::getSalesContractId, salesContract.getId()).list();
        if (CollectionUtil.isNotEmpty(salesCommodities)) {
            salesCommodityService.removeBatchByIds(salesCommodities);
        }
        List<SalesCommodityDto> salesCommodityDtos = salesContractInfoDto.getSalesCommoditys();
        salesCommodityDtos.forEach(salesCommodityDto -> {
            salesCommodityDto.setSalesContractId(salesContract.getId());
            salesCommodityDto.setId(null);
            if (salesCommodityDto.getNumber() != null && salesCommodityDto.getPriceUnit() != null) {
                salesCommodityDto.setAmount(salesCommodityDto.getNumber().multiply(salesCommodityDto.getPriceUnit()));
            }
            salesCommodityService.saveOrUpdate(salesDataConverter.convertCommodityDo(salesCommodityDto));
        });
        // salesCommodityService.saveOrUpdateBatch(salesDataConverter.convertCommodityDo(salesCommodityDtos));
        return salesContract.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveContractTerms(ContractTermsDto contractTermsDto, HttpServletResponse response) {
        CustomerUser customerUser = customerUserService.getCustomerUser();
        Enterprise enterprise = enterpriseBaseService.getEnterpriseByCustomerId(customerUser.getId());
        if (enterprise == null) {
            throw new ServiceException("用户未完成认证（用户id：" + customerUser.getId() + "）", HttpStatus.BAD_REQUEST);
        }
        contractTermsDto.setContractType(ConstantUtil.SALES_CONTRACT_NO_PREFIX);
        checkContractTerms(contractTermsDto);
        ContractTerms contractTermsExist = contractTermsService.getByContractIdAndType(contractTermsDto.getContractId(),
                ConstantUtil.SALES_CONTRACT_NO_PREFIX);
        ContractTerms contractTerms = salesDataConverter.convertContractTermsDo(contractTermsDto);
        if (contractTermsExist != null) {
            contractTerms.setId(contractTermsExist.getId());
            contractTermsService.updateById(contractTerms);
        } else {
            contractTerms.setContractId(contractTermsDto.getContractId());
            contractTermsService.save(contractTerms);
        }
        List<ContractTermsExtend> contractTermsExtendsExist = contractTermsExtendService.lambdaQuery()
                .eq(ContractTermsExtend::getContractTermsId, contractTerms.getId()).list();
        if (CollectionUtil.isNotEmpty(contractTermsExtendsExist)) {
            contractTermsExtendService.removeBatchByIds(contractTermsExtendsExist);
        }
        if (CollectionUtil.isNotEmpty(contractTermsDto.getPaymentInfo())) {
            for (ContractTermsExtend contractTermsExtend : contractTermsDto.getPaymentInfo()) {
                contractTermsExtend.setId(null);
                contractTermsExtend.setContractTermsId(contractTerms.getId());
            }
            contractTermsExtendService.saveOrUpdateBatch(contractTermsDto.getPaymentInfo());
        }
        if (CollectionUtil.isNotEmpty(contractTermsDto.getTitleInfo())) {
            for (ContractTermsExtend contractTermsExtend : contractTermsDto.getTitleInfo()) {
                contractTermsExtend.setId(null);
                contractTermsExtend.setContractTermsId(contractTerms.getId());
            }
            contractTermsExtendService.saveOrUpdateBatch(contractTermsDto.getTitleInfo());
        }
        Long fileId = null;
        if (SubmitStatus.FORMAL.getCode().equals(contractTermsDto.getSubmitStatus())) {
            // SalesContract salesContract = salesContractService.lambdaQuery()
            // .eq(SalesContract::getContractNo, contractTermsDto.getContractNo()).eq(SalesContract::getDeleted, 0)
            // .one();
            SalesContract salesContract = salesContractService.getById(contractTermsDto.getContractId());
            salesContract.setContractStatus(ContractStatus.TAKE_EFFECT.getCode());
            salesContract.setSubmitStatus(SubmitStatus.FORMAL.getCode());
            if (salesContract.getTemplateType()) {
                salesContract.setContractStatus(ContractStatus.TO_BE_UPLOADED.getCode());
                ContractFile contractFile = handleInkassoContractFile(salesContract, customerUser, contractTerms,
                        contractTermsDto.getPaymentInfo(), contractTermsDto.getTitleInfo());
                salesContract.setContractNo(contractFile.getContractNo());
                try {
                    TFileStorage tFileStorage = tFileStorageService
                            .getFileStorageById(contractFile.getUnsignFileStorageId());
                    String objName = tFileStorage.getPath();
                    String fileName = tFileStorage.getOriginalName();
                    // InputStream in = ossUtil.downloadFile(objName);
                    // OutputStream out = response.getOutputStream();
                    // FileUtils.setAttachmentResponseHeader(response, fileName);
                    // FileUtils.writeInputStream(in, out);
                    contractFileService.save(contractFile);
                    fileId = tFileStorage.getId();
                } catch (Exception e) {
                    log.error("文件下载失败,合同编号={},客户id={},异常原因={}", salesContract.getContractNo(), customerUser.getId(), e);
                    throw new ValidatorException(HttpStatus.ERROR, "文件下载失败！");
                }
            }
            salesContract.setHasPurchaseContract((DictConstants.EXPORT_TYPE_PROXY.equals(enterprise.getExportType())
                    || (!DictConstants.ENTERPRISE_TYPE_PRODUCE.equals(enterprise.getEnterpriseType())
                    || !DictConstants.ENTERPRISE_TYPE_PRODUCE_EXTERNAL.equals(enterprise.getEnterpriseType()))));
            salesContractService.updateById(salesContract);
            purchaseContractService.createPurchaseContract(salesContract.getId());
        }
        return fileId;
    }

    @Override
    public SalesContractInfoVo getSalesContractDetails(Long contractId) {
        return salesContractService.getSalesContractDetails(contractId);
    }

    @Override
    public GridPage<SalesContractVo> getSalesContractPage(ContractSearchDto contractSearch) {
        CustomerUser customerUser = customerUserService.getCustomerUser();
        contractSearch.setCustomerUserId(customerUser.getId());
        contractSearch.setPoint(true);
        Page<SalesContractVo> page = PageHelper.startPage(contractSearch.getPage(), contractSearch.getRows());
        List<SalesContractVo> rows = salesContractService.getSalesContractInfo(contractSearch);
        return new GridPage<>(contractSearch.getPage(), contractSearch.getRows(), page.getTotal(), rows);
    }

    @Override
    public Boolean deleteSalesContract(Long contractId) {
        return salesContractService.deleteSalesContract(contractId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Deprecated
    public Boolean uploadContract(Long contractId, HttpServletRequest request) {
        MultipartFile transferFile = null;
        if (request instanceof MultipartHttpServletRequest) {
            transferFile = ((MultipartHttpServletRequest) request).getFile("file");
        }
        if (transferFile == null) {
            throw new ValidatorException(HttpStatus.ERROR, "请您上传合同文件！");
        }
        SalesContract salesContract = salesContractService.getById(contractId);
        ContractFile contractFileExist = contractFileService.lambdaQuery()
                .eq(ContractFile::getContractNo, salesContract.getContractNo()).eq(ContractFile::getDeleted, 0).one();
        if (salesContract.getTemplateType() && contractFileExist == null) {
            throw new ValidatorException(HttpStatus.ERROR, "长银合同还未生成！");
        }
        try {
            if (contractFileExist != null) {
                TFileStorage fileStorage = ossFileService.addStorage(transferFile, FileModuleEnum.SIGNED_CONTRACT);
                contractFileExist.setSignedFileStorageId(fileStorage.getId());
                contractFileService.updateById(contractFileExist);
            } else {
                CustomerUser customerUser = customerUserService.getCustomerUser();
                ContractFile contractFile = new ContractFile();
                contractFile.setSignFileType(FileTypeEnum.SALES_CONTRACT.getCode());
                contractFile.setGenerationTime(LocalDateTime.now());
                contractFile.setOperatorName(customerUser.getNickname());
                TFileStorage fileStorage = ossFileService.addStorage(transferFile, FileModuleEnum.SIGNED_CONTRACT);
                contractFile.setContractNo(salesContract.getContractNo());
                contractFile.setUnsignFileStorageId(fileStorage.getId());
                contractFile.setSignedFileStorageId(fileStorage.getId());
                contractFileService.save(contractFile);
            }
            salesContract.setContractStatus(ContractStatus.TAKE_EFFECT.getCode());
            salesContractService.updateById(salesContract);
        } catch (Exception e) {
            log.error("合同编号={},上传合同文件失败,异常原因={}", salesContract.getContractNo(), e);
            throw new ValidatorException(HttpStatus.ERROR, "上传合同文件失败！");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean uploadContract(SalesUploadContractDto salesUploadContractDto) {
        SalesContract salesContract = salesContractService.getById(salesUploadContractDto.getContractId());
        if (salesContract == null) {
            throw new ValidatorException(HttpStatus.BAD_REQUEST, "销售合同不存在！");
        }
        CustomerUser customerUser = customerUserService.getCustomerUser();
        ContractFile contractFileExist = contractFileService.lambdaQuery()
                .eq(ContractFile::getContractNo, salesContract.getContractNo())
                .eq(ContractFile::getCustomerUserId, customerUser.getId()).eq(ContractFile::getDeleted, 0).one();
        if (salesContract.getTemplateType() && contractFileExist == null) {
            throw new ValidatorException(HttpStatus.ERROR, "长银合同还未生成！");
        }
        TFileStorage fileStorage = tFileStorageService.getFileStorageById(salesUploadContractDto.getFileId());
        if (fileStorage == null) {
            throw new ValidatorException(HttpStatus.BAD_REQUEST,
                    "文件不存在（文件id：" + salesUploadContractDto.getFileId() + "）");
        }
        salesContract.setSignDate(salesUploadContractDto.getSignDate());
        if (contractFileExist != null) {
            contractFileExist.setSignedFileStorageId(fileStorage.getId());
            contractFileService.updateById(contractFileExist);
        } else {
            ContractFile contractFile = new ContractFile();
            contractFile.setSignFileType(FileTypeEnum.SALES_CONTRACT.getCode());
            contractFile.setGenerationTime(LocalDateTime.now());
            contractFile.setOperatorName(customerUser.getNickname());
            contractFile.setContractNo(salesContract.getContractNo());
            contractFile.setUnsignFileStorageId(fileStorage.getId());
            contractFile.setSignedFileStorageId(fileStorage.getId());
            contractFile.setCustomerUserId(customerUser.getId());
            contractFileService.save(contractFile);
        }
        salesContract.setContractStatus(ContractStatus.TAKE_EFFECT.getCode());
        salesContractService.updateById(salesContract);
        return true;
    }

    @Override
    public Boolean downloadContract(Long contractId, HttpServletRequest request, HttpServletResponse response) {
        CustomerUser customerUser = customerUserService.getCustomerUser();
        SalesContract salesContract = salesContractService.getById(contractId);
        ContractFile contractFileExist = contractFileService.lambdaQuery()
                .eq(ContractFile::getContractNo, salesContract.getContractNo())
                .eq(ContractFile::getCustomerUserId, customerUser.getId()).eq(ContractFile::getDeleted, 0).one();
        Long fileId;
        if (!salesContract.getTemplateType()) {
            fileId = contractFileExist.getSignedFileStorageId();
        } else {
            if (ContractStatus.TAKE_EFFECT.getCode().equals(salesContract.getContractStatus())
                    || ContractStatus.COMPLETED.getCode().equals(salesContract.getContractStatus())) {
                fileId = contractFileExist.getSignedFileStorageId();
            } else {
                fileId = contractFileExist.getUnsignFileStorageId();
            }
        }
        TFileStorage tFileStorage = tFileStorageService.getFileStorageById(fileId);
        InputStream in = ossUtil.downloadFile(tFileStorage.getPath());
        FileDownUtils.downloadFile(response, in, tFileStorage.getOriginalName());
        return true;
    }

    @Override
    public ImportCommodityVo importCommodityFile(MultipartFile file) {
        if (file == null) {
            throw new ValidatorException(HttpStatus.ERROR, "请您上传商品文件！");
        }
        ExcelImportUtils excelImportUtils = new ExcelImportUtils(file);
        Sheet sheet = excelImportUtils.readFile();
        ImportCommodityVo importCommodityVo = new ImportCommodityVo();
        List<SalesCommodityDto> pass = new ArrayList<>();
        List<SalesCommodityDto> error = new ArrayList<>();
        Iterator<Row> rows = sheet.rowIterator();
        CustomerUser customerUser = customerUserService.getCustomerUser();
        EnterpriseDto enterpriseDto = enterpriseService.queryMyEnterprise();
        String exportType = enterpriseDto.getExportType();
        Map<String, String> paramsHsCode = new HashMap<>();
        while (rows.hasNext()) {
            Row row = rows.next();
            if (row.getRowNum() == 0) {
                continue;
            }
            Cell cell = row.getCell(0);
            String cellValue = getCellValue(cell);
            SalesCommodityDto salesCommodityDto = new SalesCommodityDto();
            StringBuffer stringBuffer = new StringBuffer();
            if (DictConstants.EXPORT_TYPE_SELF.equals(exportType)
                    && !DictConstants.ENTERPRISE_TYPE_PRODUCE.equals(enterpriseDto.getEnterpriseType())
                    && !DictConstants.ENTERPRISE_TYPE_PRODUCE_EXTERNAL.equals(enterpriseDto.getEnterpriseType())) {
                if (StringUtils.isNotBlank(cellValue)) {
                    String entityName = cellValue.trim();
                    VendorEntity vendorEntity = iVendorEntityService.lambdaQuery()
                            .eq(VendorEntity::getEntityName, entityName)
                            .eq(VendorEntity::getCustomerUserId, customerUser.getId()).eq(VendorEntity::getDeleted, 0)
                            .one();
                    if (vendorEntity != null) {
                        salesCommodityDto.setEntityNo(vendorEntity.getEntityNo());
                    } else {
                        stringBuffer.append("供应商名称不存在,");
                    }
                    salesCommodityDto.setEntityName(entityName);
                } else {
                    stringBuffer.append("供应商名称为空,");
                }
            } else {
                salesCommodityDto.setEntityName(cellValue);
            }
            cell = row.getCell(1);
            cellValue = getCellValue(cell);
            if (StringUtils.isNotBlank(cellValue)) {
                salesCommodityDto.setName(cellValue);
            } else {
                stringBuffer.append("商品名称为空,");
            }
            cell = row.getCell(2);
            cellValue = getCellValue(cell);
            if (StringUtils.isNotBlank(cellValue)) {
                salesCommodityDto.setHsCode(cellValue);
                List<SalesCommodityDto> salesCommodityDtos = salesCommodityService.getXiaoTuCommodityList(
                        salesCommodityDto.getHsCode(), customerUser.getXtUid(), customerUser.getId(), true);
                if (salesCommodityDtos != null && salesCommodityDtos.size() > 0) {
                    SalesCommodityDto salesCommodityTemp = salesCommodityDtos.stream()
                            .filter(s -> salesCommodityDto.getHsCode().equals(s.getHsCode())).findAny().orElse(null);
                    if (salesCommodityTemp == null) {
                        stringBuffer.append("商品不存在,");
                    } else if (salesCommodityTemp != null && StringUtils.isNotEmpty(salesCommodityTemp.getErrors())) {
                        stringBuffer.append(salesCommodityTemp.getErrors() + ",");
                    }
                    List<SalesCommodityDto> salesCommodityDtosTemp = salesCommodityDtos.stream()
                            .filter(s -> !salesCommodityDto.getHsCode().equals(s.getHsCode()))
                            .collect(Collectors.toList());
                    for (SalesCommodityDto commodityDto : salesCommodityDtosTemp) {
                        pass.add(commodityDto);
                        continue;
                    }
                } else {
                    stringBuffer.append("商品不存在,");
                }
            } else {
                stringBuffer.append("HS编码为空,");
            }
            cell = row.getCell(3);
            cellValue = getCellValue(cell);
            if (StringUtils.isNotBlank(cellValue)) {
                salesCommodityDto.setDeclarationName(cellValue);
                if (StringUtils.isNotEmpty(salesCommodityDto.getHsCode())) {
                    String hsCode = paramsHsCode.get(cellValue);
                    if (paramsHsCode.get(cellValue) != null && !hsCode.equals(salesCommodityDto.getHsCode())) {
                        stringBuffer.append("报关品名不同HS编码存在重复,");
                    } else {
                        paramsHsCode.put(cellValue, salesCommodityDto.getHsCode());
                    }
                }
            } else {
                stringBuffer.append("报关品名为空,");
            }
            cell = row.getCell(4);
            cellValue = getCellValue(cell);
            salesCommodityDto.setModel(cellValue);
            cell = row.getCell(5);
            cellValue = getCellValue(cell);
            if (StringUtils.isNotBlank(cellValue)) {
                salesCommodityDto.setMeasurementUnit(cellValue);
            } else {
                stringBuffer.append("计量单位为空,");
            }
            cell = row.getCell(6);
            cellValue = getCellValue(cell);
            if (StringUtils.isNotBlank(cellValue)) {
                salesCommodityDto.setPackSpec(cellValue);
            } else {
                stringBuffer.append("包装规格为空,");
            }
            cell = row.getCell(7);
            cellValue = getCellValue(cell);
            if (StringUtils.isNotBlank(cellValue)) {
                if (cellValue.contains(".")) {
                    cellValue = cellValue.split("\\.")[0];
                }
                salesCommodityDto.setNumber(new BigDecimal(cellValue));
            } else {
                stringBuffer.append("数量为空,");
            }
            cell = row.getCell(8);
            cellValue = getCellValue(cell);
            if (StringUtils.isNotBlank(cellValue)) {
                salesCommodityDto.setPriceUnit(new BigDecimal(cellValue));
            } else {
                stringBuffer.append("销售单价为空,");
            }
            // cell = row.getCell(7);
            // if (cell != null && StringUtils.isNotBlank(cell.getStringCellValue())) {
            // salesCommodityDto.setAmount(new BigDecimal(cell.getStringCellValue()));
            // } else {
            // stringBuffer.append("商品金额为空,");
            // }
            if (stringBuffer != null && stringBuffer.length() > 0) {
                salesCommodityDto.setErrorsValidator(stringBuffer.deleteCharAt(stringBuffer.length() - 1).toString());
                error.add(salesCommodityDto);
            } else {
                pass.add(salesCommodityDto);
            }
        }
        importCommodityVo.setPass(pass);
        importCommodityVo.setError(error);
        return importCommodityVo;
    }

    @Override
    public List<SalesCommodityDto> getXiaoTuCommodityList(String name) {
        CustomerUser customerUser = customerUserService.getCustomerUser();
        return salesCommodityService.getXiaoTuCommodityList(name, customerUser.getXtUid(), customerUser.getId());
    }

    @Override
    public List<SalesCommoditySpidDto> getXiaoTuCommoditySpidList(String name) {
        CustomerUser customerUser = customerUserService.getCustomerUser();
        return salesCommodityService.getXiaoTuCommoditySpidList(name, customerUser.getXtUid(), customerUser.getId());
    }

    @Override
    public Boolean downloadTemplates(HttpServletRequest request, HttpServletResponse response) {
        InputStream inputStream = null;
        OutputStream os = null;
        try {
            String fileName = "商品模板.xlsx";
            String filePath = path + fileName;
            inputStream = new FileInputStream(filePath);
            FileUtils.setAttachmentResponseHeader(response, fileName);
            os = response.getOutputStream();
            int read;
            while ((read = inputStream.read()) != -1) {
                os.write(read);
            }
            os.close();
        } catch (Exception e) {
            log.error("下载商品模板失败", e);
            throw new ValidatorException(HttpStatus.ERROR, "下载商品模板失败！");
        } finally {
            try {
                IOUtils.close(os);
                IOUtils.close(inputStream);
            } catch (IOException e) {
                log.error("关闭流失败:" + e.getMessage());
            }
        }
        return true;
    }

    /**
     * 校验销售合同参数
     *
     * @param salesContractDto
     * @param transferFile
     * @param salesContractExist
     */
    private void checkSalesContractParameter(SalesContractDto salesContractDto, MultipartFile transferFile,
                                             SalesContract salesContractExist) {
        if (!salesContractDto.getTemplateType()) {
            if (salesContractDto.getContractNo() == null || salesContractDto.getSignDate() == null) {
                throw new ValidatorException(HttpStatus.ERROR, "合同编号与签署日期不能为空！");
            }
            if (transferFile == null) {
                throw new ValidatorException(HttpStatus.ERROR, "请您上传合同！");
            }
            // 获取文件名
            String filename = transferFile.getOriginalFilename();
            String suffix;
            int dotIndex = filename.lastIndexOf('.');
            if (dotIndex == -1 || dotIndex == filename.length() - 1) {
                suffix = "";
            } else {
                suffix = filename.substring(dotIndex + 1);
            }
            if ("pdf".equalsIgnoreCase(suffix)) {
                throw new ValidatorException(HttpStatus.ERROR, "合同文件格式必须为pdf格式");
            }
            boolean meetLimit = MultipartFileUtil.checkFileSize(transferFile, 20, "M");
            if (!meetLimit) {
                throw new ValidatorException(HttpStatus.ERROR, "合同文件大小请控制在20M以内");
            }
        }
        if (salesContractExist != null && SubmitStatus.FORMAL.getCode().equals(salesContractExist.getSubmitStatus())) {
            throw new ValidatorException(HttpStatus.ERROR, "该合同编号已存在正式合同，请勿重复提交！");
        }
    }

    /***
     * 处理合同文件
     *
     * @param salesContractDto
     * @param customerUser
     * @param transferFile
     * @param isTemplate
     * @return 合同文件信息
     */
    private ContractFile handleContractFile(SalesContractDto salesContractDto, CustomerUser customerUser,
                                            MultipartFile transferFile, boolean isTemplate) {
        try {
            ContractFile contractFile = new ContractFile();
            contractFile.setSignFileType(FileTypeEnum.SALES_CONTRACT.getCode());
            contractFile.setGenerationTime(LocalDateTime.now());
            contractFile.setOperatorName(customerUser.getNickname());
            contractFile.setCustomerUserId(customerUser.getId());
            if (salesContractDto.getTemplateType()) {
                if (isTemplate) {
                    // 生成合同文件
                    contractFile.setContractNo(serialNumberGenerator.nextValue(ConstantUtil.SALES_CONTRACT_NO_PREFIX));
                    // ContractGenInput input = new ContractGenInput();
                    // input.setBizNo(contractFile.getContractNo());
                    // input.setUserId(customerUser.getId());
                    // input.setBizType(FileTypeEnum.SALES_CONTRACT.getCode());
                    ContractGenInputItem contractGenInputItem = new ContractGenInputItem();
                    contractGenInputItem.setContractName(salesContractDto.getContractName());
                    // todo 缺失合同模板
                    ContractGenOutputItem contractGenOutput = contractService
                            .generateSingleContract(contractGenInputItem, customerUser.getId());
                    contractFile.setUnsignFileStorageId(contractGenOutput.getFileId());
                }
            } else {
                // TFileStorage fileStorage = ossFileService.addStorage(transferFile, FileModuleEnum.SIGNED_CONTRACT);
                TFileStorage fileStorage = tFileStorageService.getFileStorageById(salesContractDto.getFileId());
                if (SubmitStatus.DRAFT.getCode().equals(salesContractDto.getSubmitStatus())) {
                    if (fileStorage == null) {
                        return null;
                    }
                } else if (fileStorage == null) {
                    throw new ValidatorException(HttpStatus.BAD_REQUEST,
                            "文件不存在（文件id：" + salesContractDto.getFileId() + "）");
                }
                contractFile.setContractNo(salesContractDto.getContractNo());
                contractFile.setUnsignFileStorageId(fileStorage.getId());
                contractFile.setSignedFileStorageId(fileStorage.getId());
            }
            return contractFile;
        } catch (ServiceException e) {
            log.error("上传合同文件失败,合同编号={},客户id={},异常原因={}", salesContractDto.getContractNo(), customerUser.getId(), e);
            throw new ValidatorException(HttpStatus.ERROR, "合同文件处理失败，请稍后再试！");
        }
    }

    /**
     * 处理合同文件
     *
     * @param salesContract
     * @param customerUser
     * @param contractTerms
     * @param paymentInfos
     * @return
     */
    private ContractFile handleInkassoContractFile(SalesContract salesContract, CustomerUser customerUser,
                                                   ContractTerms contractTerms, List<ContractTermsExtend> paymentInfos, List<ContractTermsExtend> titleInfos) {
        try {
            List<SalesCommodity> salesCommodities = salesCommodityService.lambdaQuery()
                    .eq(SalesCommodity::getSalesContractId, salesContract.getId()).eq(SalesCommodity::getDeleted, 0)
                    .list();
            ContractFile contractFile = new ContractFile();
            contractFile.setSignFileType(FileTypeEnum.SALES_CONTRACT.getCode());
            contractFile.setGenerationTime(LocalDateTime.now());
            contractFile.setOperatorName(customerUser.getNickname());
            contractFile.setCustomerUserId(customerUser.getId());
            contractFile.setContractNo(serialNumberGenerator.nextValue(ConstantUtil.SALES_CONTRACT_NO_PREFIX));
            ContractTemplateDto contractTemplateDto = new ContractTemplateDto();
            contractTemplateDto.setContractNo(contractFile.getContractNo());
            contractTemplateDto.setBuyer(salesContract.getImporterEnterpriseName());
            EnterpriseDto enterpriseDto = enterpriseService.queryMyEnterprise();
            if (DictConstants.EXPORT_TYPE_PROXY.equals(enterpriseDto.getExportType())) {
                TradingPlatform tradingPlatform = tradingPlatformBaseService.lambdaQuery()
                        .eq(TradingPlatform::getCertNo, salesContract.getAgencyCertNo()).one();
                if (tradingPlatform != null) {
                    contractTemplateDto.setSellerContact(tradingPlatform.getContactName());
                    contractTemplateDto.setSellerAddress(tradingPlatform.getBusinessAddress());
                    contractTemplateDto.setSellerEmail(tradingPlatform.getContactEmail());
                    contractTemplateDto.setSeller(salesContract.getAgencyEnterpriseName());
                }
            } else {
                EnterpriseRelatedPerson contact = relatedPersonBaseService
                        .getContactByChangeRecordId(enterpriseDto.getChangeRecordId());
                contractTemplateDto.setSeller(enterpriseDto.getName());
                contractTemplateDto.setSellerContact(contact.getName());
                contractTemplateDto.setSellerAddress(contact.getAddress());
                contractTemplateDto.setSellerEmail(contact.getEmail());
            }
            List<ContractCommodityDto> contractCommodityDtos = new ArrayList<>();
            for (int i = 0; i < salesCommodities.size(); i++) {
                SalesCommodity salesCommodity = salesCommodities.get(i);
                ContractCommodityDto contractCommodityDto = new ContractCommodityDto(salesCommodity);
                contractCommodityDto.setXh(String.valueOf(i + 1));
                contractCommodityDtos.add(contractCommodityDto);
            }
            BigDecimal count = BigDecimal.ZERO;
            BigDecimal pTotal = BigDecimal.ZERO;
            BigDecimal aTotal = BigDecimal.ZERO;
            for (SalesCommodity salesCommodity : salesCommodities) {
                count = count.add(salesCommodity.getNumber());
                pTotal = pTotal.add(salesCommodity.getPriceUnit());
                aTotal = aTotal.add(salesCommodity.getAmount());
                contractTemplateDto.setCurrency(salesCommodity.getCurrency());
            }
            contractTemplateDto.setCTotal(String.valueOf(count));
            contractTemplateDto.setPTotal(pTotal.toPlainString());
            contractTemplateDto.setATotal(aTotal.toPlainString());
            contractTemplateDto.setRemark(contractTerms.getRemark());
            contractTemplateDto.setPortDeparture(salesContract.getPortDeparture());
            contractTemplateDto.setPortDestination(salesContract.getPortDestination());
            contractTemplateDto.setTradeTerms(salesContract.getTradeTerms());
            StringBuffer paymentInfo = new StringBuffer();
            String paymentWay = iSysDictDataService.selectDictLabel("payment_way", contractTerms.getPaymentWay());
            paymentInfo.append(paymentWay).append("，");
            for (ContractTermsExtend info : paymentInfos) {
                paymentInfo.append(info.getPaymentTime()).append(info.getPaymentTerm()).append("天支付")
                        .append(info.getPaymentRatio()).append("%").append(info.getPaymentName()).append("，");
            }
            contractTemplateDto.setPaymentTerms(paymentInfo.deleteCharAt(paymentInfo.length() - 1).toString());
            contractTemplateDto.setAccountName(contractTerms.getAccountName());
            contractTemplateDto.setAccountNumber(contractTerms.getAccountNumber());
            contractTemplateDto.setSwiftCode(contractTerms.getSwiftCode());
            contractTemplateDto.setOpeningBank(contractTerms.getOpeningBank());
            ImporterEntity importerEntity = IImporterEntityService.getByCertNo(salesContract.getImporterCertNo());
            if (importerEntity != null) {
                contractTemplateDto.setBuyerContact(importerEntity.getContactName());
                contractTemplateDto.setBuyerAddress(importerEntity.getBusinessAddress());
                contractTemplateDto.setBuyerEmail(importerEntity.getContactEmail());
            }
            if (CollectionUtil.isEmpty(titleInfos)) {
                contractTemplateDto.setTitleInfo("无。");
            } else {
                if (titleInfos.size() == 1) {
                    ContractTermsExtend titleInfo = titleInfos.get(0);
                    contractTemplateDto.setTitleInfo("    " + titleInfo.getTermTitle() + "，" + titleInfo.getContent() + "。");
                } else {
                    StringBuffer title = new StringBuffer();
                    for (int i = 0; i < titleInfos.size(); i++) {
                        ContractTermsExtend titleInfo = titleInfos.get(i);
                        title.append("   （").append(i + 1).append("）").append(titleInfo.getTermTitle()).append("，")
                                .append(titleInfo.getContent()).append("；").append("\n");
                    }
                    contractTemplateDto.setTitleInfo(title.toString());
                }
            }
            ContractGenInputItem contractGenInputItem = new ContractGenInputItem();
            contractGenInputItem.setContractName(salesContract.getContractName());
            String templateCode = fileTemplateService.selectByFileType(FileTypeEnum.SALES_CONTRACT.getCode())
                    .getTemplateCode();
            contractGenInputItem.setTemplateCode(templateCode);
            Map<String, Object> params = BeanUtil.beanToMap(contractTemplateDto);
            params.put(SaleOrderConstant.ORDER_INVOICE_GOODS_LIST_KEY, contractCommodityDtos);
            contractGenInputItem.setParams(params);
            LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
            contractGenInputItem.setConfig(
                    Configure.builder().bind(SaleOrderConstant.ORDER_INVOICE_GOODS_LIST_KEY, policy).build());
            ContractGenOutputItem outputItem = contractService.generateSingleContract(contractGenInputItem,
                    salesContract.getCustomerUserId());
            contractFile.setUnsignFileStorageId(outputItem.getFileId());
            return contractFile;
        } catch (Exception e) {
            log.error("生成合同文件失败,合同编号={},客户id={},异常原因={}", salesContract.getContractNo(), customerUser.getId(), e);
            throw new ValidatorException(HttpStatus.ERROR, "合同文件处理失败，请稍后再试！");
        }
    }

    private void preVerification(SalesContractInfoDto salesContractDto) {
        if (SubmitStatus.INTERMEDIATE_STATE.getCode().equals(salesContractDto.getSalesContract().getSubmitStatus())) {
            // 校验参数
            if (StringUtils.isNotEmpty(salesContractDto.getSalesContract().getContractNo())) {
                SalesContract salesContract = salesContractService.getByContractNo(
                        salesContractDto.getSalesContract().getContractNo(),
                        salesContractDto.getSalesContract().getCustomerUserId());
                if (salesContract != null && !salesContract.getId().equals(salesContractDto.getSalesContract().getId())) {
                    throw new ValidatorException(HttpStatus.BAD_REQUEST, "请您检查合同编号，合同编号存在重复");
                }
            }
            EnterpriseDto enterpriseDto = enterpriseService.queryMyEnterprise();
            String exportType = enterpriseDto.getExportType();
            if (DictConstants.EXPORT_TYPE_PROXY.equals(exportType)) {
                if (StringUtils.isBlank(salesContractDto.getSalesContract().getAgencyCertNo())) {
                    throw new ValidatorException(HttpStatus.BAD_REQUEST, "代理公司信息不能为空！");
                }
                if (salesContractDto.getSalesContract().getExchangeRate() == null) {
                    throw new ValidatorException(HttpStatus.BAD_REQUEST, "代理出口模式下成交汇率不能为空！");
                }
            }
            ValidatorUtil.validator(ValidatorGroup.ValidatorType.SUBMIT, salesContractDto.getSalesContract());
            if (CollectionUtil.isEmpty(salesContractDto.getSalesCommoditys())) {
                throw new ValidatorException(HttpStatus.BAD_REQUEST, "需要添加商品信息！");
            }
            Map<String, Integer> paramsName = new HashMap<>();
            Map<String, String> paramsHsCode = new HashMap<>();
            for (int i = 0; i < salesContractDto.getSalesCommoditys().size(); i++) {
                SalesCommodityDto salesCommodityDto = salesContractDto.getSalesCommoditys().get(i);
                ValidatorUtil.validator(ValidatorGroup.ValidatorType.SUBMIT, salesCommodityDto, i + 1);
                String hsCode = paramsHsCode.get(salesCommodityDto.getDeclarationName());
                if (hsCode != null && !hsCode.equals(salesCommodityDto.getHsCode())) {
                    int line = paramsName.get(salesCommodityDto.getDeclarationName());
                    int lineTemp = i + 1;
                    throw new ValidatorException(HttpStatus.BAD_REQUEST,
                            "商品信息第" + lineTemp + "行，报关品名与第" + line + "不能相同");
                } else {
                    paramsName.put(salesCommodityDto.getDeclarationName(), i + 1);
                    paramsHsCode.put(salesCommodityDto.getDeclarationName(), salesCommodityDto.getHsCode());
                }
                if (DictConstants.EXPORT_TYPE_SELF.equals(exportType)
                        && !DictConstants.ENTERPRISE_TYPE_PRODUCE.equals(enterpriseDto.getEnterpriseType())
                        && !DictConstants.ENTERPRISE_TYPE_PRODUCE_EXTERNAL.equals(enterpriseDto.getEnterpriseType())) {
                    if (StringUtils.isBlank(salesCommodityDto.getEntityNo())) {
                        throw new ValidatorException(HttpStatus.BAD_REQUEST, "商品信息第" + i + 1 + "行，供应商不能为空");
                    }
                }
            }
        }
    }

    /**
     * 校验合同条款
     *
     * @param contractTermsDto
     */
    private void checkContractTerms(ContractTermsDto contractTermsDto) {
        if (SubmitStatus.FORMAL.getCode().equals(contractTermsDto.getSubmitStatus())) {
            ValidatorUtil.validator(ValidatorGroup.ValidatorType.SUBMIT, contractTermsDto);
            if (StringUtils.isBlank(contractTermsDto.getPaymentWay())) {
                throw new ValidatorException(HttpStatus.BAD_REQUEST, "付款币种不能为空！");
            }
            if (CollectionUtil.isEmpty(contractTermsDto.getPaymentInfo())) {
                throw new ValidatorException(HttpStatus.BAD_REQUEST, "付款列表不能为空！");
            } else {
                ContractTermsExtend contractTermsExtend = contractTermsDto.getPaymentInfo().stream()
                        .max(Comparator.comparing(ContractTermsExtend::getPaymentRatio)).get();
                if (!contractTermsExtend.getPaymentTerm().equals(contractTermsDto.getSettlementCycle())) {
                    throw new ValidatorException(HttpStatus.BAD_REQUEST, "付款比例最大付款期限不等于结算周期！");
                }
                BigDecimal totalRatio = contractTermsDto.getPaymentInfo().stream()
                        .map(ContractTermsExtend::getPaymentRatio).reduce(BigDecimal.ZERO, BigDecimal::add);
                if (totalRatio.compareTo(new BigDecimal("100")) != 0) {
                    throw new ServiceException("付款比例总和必须为100%", HttpStatus.BAD_REQUEST);
                }
            }
        }
    }

    private String getCellValue(Cell cell) {
        String value = "";
        if (cell == null) {
            return value;
        }
        if (cell.getCellType() == CellType.NUMERIC) {
            value = String.valueOf(cell.getNumericCellValue());
        } else if (cell.getCellType() == CellType.STRING) {
            value = cell.getStringCellValue();
        } else if (cell.getCellType() == CellType.BOOLEAN) {
            value = String.valueOf(cell.getBooleanCellValue());
        } else if (cell.getCellType() == CellType.FORMULA) {
            value = cell.getCellFormula();
        } else if (cell.getCellType() == CellType.BLANK) {
            value = "";
        }
        return value;
    }

    private void saveContractFile(SalesContractDto salesContractDto, ContractFile contractFile) {
        if (!salesContractDto.getTemplateType() && contractFile != null) {
            // 2、保存销售合同文件信息
            ContractFile contractFileExist = contractFileService.lambdaQuery()
                    .eq(ContractFile::getContractNo, contractFile.getContractNo()).eq(ContractFile::getDeleted, 0)
                    .one();
            if (contractFileExist != null) {
                contractFile.setId(contractFileExist.getId());
                contractFileService.updateById(contractFile);
            } else {
                contractFileService.save(contractFile);
            }
        }
    }
}
