/**
 * @filename:SalesContractServiceImpl 2024-09-03
 * @project KJT v1.0.0 Copyright(c) 2024 wanglang Co. Ltd. All right reserved.
 */
package com.trade.service.trade.salescontract.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.trade.common.constant.HttpStatus;
import com.trade.common.enums.ContractStatus;
import com.trade.common.enums.SubmitStatus;
import com.trade.common.exception.ValidatorException;
import com.trade.common.utils.StringUtils;
import com.trade.service.enterprise.customer.domain.Enterprise;
import com.trade.service.enterprise.customer.service.EnterpriseBaseService;
import com.trade.common.utils.ConstantUtil;
import com.trade.service.filestorage.dto.FileAbstractDto;
import com.trade.service.filestorage.entity.TFileStorage;
import com.trade.service.filestorage.service.TFileStorageService;
import com.trade.service.finance.paymentcollection.vo.EntrySalesContractVo;
import com.trade.service.trade.filingdoc.vo.Contract4FilingDocSearch;
import com.trade.service.trade.salescontract.dto.ContractFileDto;
import com.trade.service.trade.salescontract.dto.ContractSearchDto;
import com.trade.service.trade.salescontract.dto.ContractTermsDto;
import com.trade.service.trade.salescontract.dto.SalesContractDto;
import com.trade.service.trade.salescontract.mapper.SalesContractMapper;
import com.trade.service.trade.filingdoc.vo.SalesContract4FilingDocVO;
import com.trade.service.trade.salescontract.vo.SalesContractInfoVo;
import com.trade.service.trade.salescontract.vo.SalesContractVo;
import com.trade.service.trade.salescontract.domain.*;
import com.trade.service.trade.salescontract.service.*;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:销售合同基础信息服务实现
 * @version: v1.0.0
 * @author: wanglang
 */
@Service
public class SalesContractServiceImpl extends ServiceImpl<SalesContractMapper, SalesContract> implements SalesContractService {

    @Resource
    private SalesDataConverter salesDataConverter;
    @Resource
    private SalesCommodityService salesCommodityService;
    @Resource
    private ContractFileService contractFileService;
    @Resource
    private TFileStorageService tFileStorageService;
    @Resource
    private ContractTermsService contractTermsService;
    @Resource
    private ContractTermsExtendService contractTermsExtendService;
    @Resource
    private EnterpriseBaseService enterpriseBaseService;

    @Override
    public SalesContractInfoVo getSalesContractDetails(Long contractId) {
        SalesContract salesContract = this.baseMapper.selectById(contractId);
        if (salesContract == null) {
            throw new ValidatorException(HttpStatus.ERROR, "销售合同不存在！");
        }
        SalesContractInfoVo salesContractInfoVo = new SalesContractInfoVo();
        SalesContractDto salesContractDto = salesDataConverter.convertSalesContractDto(salesContract);
        Enterprise enterprise = enterpriseBaseService.getEnterpriseByCustomerId(salesContract.getCustomerUserId());
        salesContractDto.setExportType(enterprise.getExportType());
        List<SalesCommodity> salesCommodities = salesCommodityService.queryBySalesContractId(salesContractDto.getId());
        BigDecimal amount = salesCommodities.stream().filter(s -> s.getAmount() != null).map(SalesCommodity::getAmount)
                .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        salesContractDto.setContractAmount(amount);
        salesContractInfoVo.setSalesContract(salesContractDto);
        salesContractInfoVo.setSalesCommoditys(salesDataConverter.convertCommodityDto(salesCommodities));
        ContractFile contractFile = null;
        if (StringUtils.isNotEmpty(salesContractDto.getContractNo())) {
            contractFile = contractFileService.lambdaQuery()
                    .eq(ContractFile::getContractNo, salesContractDto.getContractNo())
                    .eq(ContractFile::getCustomerUserId, salesContract.getCustomerUserId())
                    .eq(ContractFile::getDeleted, 0).one();
        }
        ContractFileDto contractFileDto = new ContractFileDto();
        if (contractFile != null) {
            TFileStorage fileStorage;
            if (ContractStatus.TAKE_EFFECT.getCode().equals(salesContractDto.getContractStatus())
                    || ContractStatus.COMPLETED.getCode().equals(salesContractDto.getContractStatus())) {
                fileStorage = tFileStorageService.getFileStorageById(contractFile.getSignedFileStorageId());
                contractFileDto.setFileId(contractFile.getSignedFileStorageId());
                contractFileDto.setId(contractFile.getSignedFileStorageId());
            } else {
                contractFileDto.setFileId(contractFile.getUnsignFileStorageId());
                contractFileDto.setId(contractFile.getUnsignFileStorageId());
                fileStorage = tFileStorageService.getFileStorageById(contractFile.getUnsignFileStorageId());
            }
            if (fileStorage != null) {
                contractFileDto.setPath(fileStorage.getOriginalName());
                contractFileDto.setOriginalName(fileStorage.getOriginalName());
            }
        }
        salesContractInfoVo.setContractFile(contractFileDto);
        ContractTermsDto contractTermsDto = contractTermsService.getDetailByContractIdAndType(contractId,
                ConstantUtil.SALES_CONTRACT_NO_PREFIX);
        salesContractInfoVo.setContractTermsDto(contractTermsDto);
        return salesContractInfoVo;
    }

    @Override
    public List<SalesContractVo> getSalesContractInfo(ContractSearchDto contractSearch) {
        List<SalesContractVo> salesContractVos = this.baseMapper.selectByCondition(contractSearch);
        salesContractVos.forEach(salesContractVo -> {
            List<SalesCommodity> salesCommodities = salesCommodityService
                    .queryBySalesContractId(salesContractVo.getId());
            BigDecimal amount = salesCommodities.stream().filter(s -> s.getAmount() != null)
                    .map(SalesCommodity::getAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
            salesContractVo.setContractAmount(amount);
        });
        return salesContractVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteSalesContract(Long contractId) {
        SalesContract salesContract = this.baseMapper.selectById(contractId);
        if (salesContract == null) {
            throw new ValidatorException(HttpStatus.ERROR, "销售合同不存在！");
        }
        if (!SubmitStatus.DRAFT.getCode().equals(salesContract.getSubmitStatus())) {
            throw new ValidatorException(HttpStatus.ERROR, "非草稿状态销售合同不允许删除！");
        }
        salesContract.setDeleted(1);
        List<SalesCommodity> salesCommodities = salesCommodityService.lambdaQuery()
                .eq(SalesCommodity::getSalesContractId, salesContract.getId()).list();
        salesCommodities.forEach(salesCommodity -> {
            salesCommodity.setDeleted(1);
        });
        ContractFile contractFile = contractFileService.lambdaQuery()
                .eq(ContractFile::getContractNo, salesContract.getContractNo())
                .eq(ContractFile::getCustomerUserId, salesContract.getCustomerUserId()).eq(ContractFile::getDeleted, 0)
                .one();
        if (contractFile != null) {
            contractFile.setDeleted(1);
            contractFileService.removeById(contractFile);
        }
        ContractTerms contractTerms = contractTermsService.getByContractIdAndType(salesContract.getId(),
                ConstantUtil.SALES_CONTRACT_NO_PREFIX);
        if (contractTerms != null) {
            contractTerms.setDeleted(1);
            contractTermsService.removeById(contractTerms);
            List<ContractTermsExtend> contractTermsExtends = contractTermsExtendService.lambdaQuery()
                    .eq(ContractTermsExtend::getContractTermsId, contractTerms.getId()).list();
            contractTermsExtends.forEach(contractTermsExtend -> {
                contractTermsExtend.setDeleted(1);
            });
            contractTermsExtendService.removeBatchByIds(contractTermsExtends);
        }
        this.baseMapper.deleteById(salesContract);
        salesCommodityService.removeBatchByIds(salesCommodities);
        return true;
    }

    @Override
    public SalesContractDto getSalesContractById(Long contractId) {
        SalesContract salesContract = this.baseMapper.selectById(contractId);
        if (salesContract == null) {
            throw new ValidatorException(HttpStatus.ERROR, "销售合同不存在！");
        }
        return salesDataConverter.convertSalesContractDto(salesContract);
    }

    @Override
    public List<SalesContractVo> querySalesContractByCustomerUserId(Long customerUserId, String importerCertNo) {
        ContractSearchDto contractSearch = new ContractSearchDto();
        contractSearch.setCustomerUserId(customerUserId);
        contractSearch.setImporterCertNo(importerCertNo);
        return this.baseMapper.selectByCondition(contractSearch).stream()
                .filter(e -> ContractStatus.TAKE_EFFECT.getCode().equals(e.getContractStatus()))
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getDestPortList(Long customerUserId) {
        if (customerUserId == null) {
            // 全量查询
            return this.lambdaQuery().list().stream().map(SalesContract::getPortDestination).distinct()
                    .collect(Collectors.toList());
        } else {
            return this.lambdaQuery().eq(SalesContract::getCustomerUserId, customerUserId).list().stream()
                    .map(SalesContract::getPortDestination).distinct().collect(Collectors.toList());
        }
    }

    @Override
    public SalesContract getByContractNo(String contractNo, Long customerUserId) {
        return this.lambdaQuery().eq(SalesContract::getContractNo, contractNo)
                .eq(SalesContract::getCustomerUserId, customerUserId).one();
    }

    @Override
    public boolean existSalesContractByImporterCertNo(String importerCertNo, Long customerUserId) {
        return this.lambdaQuery().eq(SalesContract::getImporterCertNo, importerCertNo)
                .eq(SalesContract::getCustomerUserId, customerUserId).count() > 0;
    }

    @Override
    public List<EntrySalesContractVo> selectEntrySalesContract() {
        return this.baseMapper.selectEntrySalesContract();
    }

    @Override
    public PageInfo<SalesContract4FilingDocVO> queryList4FilingDocBySearch(Contract4FilingDocSearch search) {
        PageHelper.startPage(search.getPage(), search.getRows());
        List<SalesContract4FilingDocVO> list = this.baseMapper.queryList4FilingDocBySearch(search);
        list.forEach(e -> e
                .setContractFile(new FileAbstractDto(tFileStorageService.getFileStorageById(e.getContractFileId()))));
        return new PageInfo<>(list);
    }
}
