package com.trade.admin.finance.paymentcollection.service.impl;

import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.trade.admin.business.separateaccounts.service.BSeparateAccountsService;
import com.trade.admin.enterprise.customer.dto.CustomerUserDto;
import com.trade.admin.enterprise.customer.service.CustomerUserService;
import com.trade.admin.finance.paymentcollection.dto.BankAccountDto;
import com.trade.admin.finance.paymentcollection.dto.BillingIncomeDetailDto;
import com.trade.admin.finance.paymentcollection.dto.BillingIncomeInfoDto;
import com.trade.admin.finance.paymentcollection.dto.TradeRepaymentDto;
import com.trade.admin.finance.paymentcollection.service.BPaymentCollectionService;
import com.trade.admin.system.security.utils.SecurityUtils;
import com.trade.admin.trade.exportrebate.service.ExportTaxRebateService;
import com.trade.common.constant.HttpStatus;
import com.trade.common.core.domain.ResponseResult;
import com.trade.common.core.page.GridPage;
import com.trade.common.exception.ServiceException;
import com.trade.common.utils.DateUtils;
import com.trade.common.utils.LoggerUtil;
import com.trade.common.utils.StringUtils;
import com.trade.common.utils.bean.BeanCopyUtils;
import com.trade.common.validate.ValidatorGroup;
import com.trade.common.validate.ValidatorUtil;
import com.trade.service.enterprise.customer.domain.Enterprise;
import com.trade.service.enterprise.customer.service.EnterpriseBaseService;
import com.trade.service.filestorage.dto.FileAbstractDto;
import com.trade.service.filestorage.entity.BusinessRelateFile;
import com.trade.service.filestorage.entity.TFileStorage;
import com.trade.service.filestorage.enums.FileTypeEnum;
import com.trade.service.filestorage.service.BusinessRelateFileBaseService;
import com.trade.service.filestorage.service.TFileStorageService;
import com.trade.service.finance.constant.BillingConstant;
import com.trade.service.finance.paymentcollection.domain.*;
import com.trade.service.finance.paymentcollection.dto.BillingIncomeSearchDto;
import com.trade.service.finance.paymentcollection.dto.EntryApplyDto;
import com.trade.service.finance.paymentcollection.dto.EntryReviewDto;
import com.trade.service.finance.paymentcollection.service.*;
import com.trade.service.finance.paymentcollection.vo.BillingIncomePageVo;
import com.trade.service.finance.paymentcollection.vo.EntrySalesContractDetailVo;
import com.trade.service.finance.paymentcollection.vo.EntrySalesContractVo;
import com.trade.service.trade.filingdoc.service.FilingDocService;
import com.trade.service.trade.salescontract.dto.SalesContractDto;
import com.trade.service.trade.salescontract.service.SalesContractService;
import com.trade.service.trade.salesorder.constant.SaleOrderConstant;
import com.trade.service.trade.salesorder.domain.SalesOrder;
import com.trade.service.trade.salesorder.domain.SalesOrderGoods;
import com.trade.service.trade.salesorder.dto.OrderListInfoDto;
import com.trade.service.trade.salesorder.dto.SalesOrderReceiveExtendDto;
import com.trade.service.trade.salesorder.service.ISalesOrderGoodsService;
import com.trade.service.trade.salesorder.service.ISalesOrderService;
import com.trade.service.tradingplatform.domain.TradingPlatform;
import com.trade.service.tradingplatform.service.TradingPlatformBaseService;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @description: 出入账管理实现类
 * @Author: wanglang
 * @Date: 2024/10/22
 * @Version: 1.0
 */
@Service
public class BPaymentCollectionServiceImpl implements BPaymentCollectionService {

    private static final Logger log = LoggerUtil.logger(LoggerUtil.LogFileNameEnum.SERVICES_LOG);;
    @Resource
    private SalesContractService salesContractService;
    @Resource
    private BillingIncomeService billingIncomeService;
    @Resource
    private TFileStorageService fileStorageService;
    @Resource
    private BusinessRelateFileBaseService businessRelateFileBaseService;
    @Resource
    private PaymentCollectionOperateService paymentCollectionOperateService;
    @Resource
    private BSeparateAccountsService separateAccountsService;
    @Resource
    private BillingIncomeInfoService billingIncomeInfoService;
    @Resource
    private TradingPlatformBaseService tradingPlatformBaseService;
    @Resource
    private EnterpriseBaseService enterpriseBaseService;
    @Resource
    private FilingDocService filingDocService;
    @Resource
    private ExportTaxRebateService exportTaxRebateService;
    @Resource
    private OrderIncomeAssociationService orderIncomeAssociationService;
    @Resource
    private ISalesOrderService iSalesOrderService;
    @Resource
    private OrderReceivePaymentAssociationService orderReceivePaymentAssociationService;
    @Resource
    private ISalesOrderGoodsService iSalesOrderGoodsService;
    @Resource
    private CustomerUserService customerUserService;

    @Override
    public GridPage<BillingIncomePageVo> queryListByPage(BillingIncomeSearchDto incomeSearchDto) {
        Page<BillingIncomePageVo> page = PageHelper.startPage(incomeSearchDto.getPage(), incomeSearchDto.getRows());
        List<BillingIncomePageVo> voList = billingIncomeService.findByPage(incomeSearchDto);
        return new GridPage<>(incomeSearchDto.getPage(), incomeSearchDto.getRows(), page.getTotal(), voList);
    }

    @Override
    public List<EntrySalesContractVo> getEntrySalesContractList() {
        return salesContractService.selectEntrySalesContract();
    }

    @Override
    public EntrySalesContractDetailVo getEntrySalesContractDetail(Long contractId) {
        SalesContractDto salesContractDto = salesContractService.getSalesContractById(contractId);
        EntrySalesContractDetailVo detailVo = new EntrySalesContractDetailVo();
        if (salesContractDto != null) {
            detailVo.setAgencyCertNo(salesContractDto.getAgencyCertNo());
            detailVo.setAgencyEnterpriseName(salesContractDto.getAgencyEnterpriseName());
            detailVo.setImporterCertNo(salesContractDto.getImporterCertNo());
            detailVo.setImporterEnterpriseName(salesContractDto.getImporterEnterpriseName());
            detailVo.setCustomerUserId(salesContractDto.getCustomerUserId());
            detailVo.setContractNo(salesContractDto.getContractNo());
            detailVo.setContractName(salesContractDto.getContractName());
            if (salesContractDto.getAgencyCertNo() != null) {
                TradingPlatform tradingPlatform = tradingPlatformBaseService
                        .findByCertNo(salesContractDto.getAgencyCertNo());
                detailVo.setProxyDistrictCode(tradingPlatform.getDistrictCode());
                detailVo.setAccountName(tradingPlatform.getPlatformName());
                detailVo.setAccountNumber(tradingPlatform.getBankNum());
                detailVo.setOpeningBank(tradingPlatform.getBankName());
            }
            Enterprise enterprise = enterpriseBaseService
                    .getEnterpriseByCustomerId(salesContractDto.getCustomerUserId());
            detailVo.setCustomerIdentifierNo(enterprise.getCustomerIdentifierNo());
            detailVo.setContractName(enterprise.getName());
        }
        // todo 银行账号信息待确定
        // todo 资金方信息
        return detailVo;
    }

    @Override
    public Boolean submitEntryApply(EntryApplyDto entryApplyDto) {
        BillingIncome billingIncome = BeanCopyUtils.copy(entryApplyDto, BillingIncome.class);
        billingIncome.setPaymentWay(BillingConstant.PAYMENT_WAY_ENTRY_APPLY);
        billingIncome.setPaymentType(BillingConstant.PAYMENT_TYPE_REPAYMENT);
        billingIncome.setStatus(BillingConstant.ENTRY_STATUS_UNCONFIRMED);
        String userNickName = SecurityUtils.getUserNickName();
        billingIncomeService.save(billingIncome);
        PaymentCollectionOperate paymentCollectionOperate = new PaymentCollectionOperate(billingIncome.getId(), 1);
        paymentCollectionOperate.setApplicant(userNickName);
        paymentCollectionOperate.setApplyDate(LocalDateTime.now());
        paymentCollectionOperateService.save(paymentCollectionOperate);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean submitEntryReview(EntryReviewDto reviewDto) {
        String userNickName = SecurityUtils.getUserNickName();
        BillingIncome income = billingIncomeService.getById(reviewDto.getId());
        if (income == null) {
            throw new ServiceException("未找到该出入账申请记录");
        }
        TFileStorage fileStorage = fileStorageService.getFileStorageById(reviewDto.getFileId());
        if (fileStorage != null) {
            BusinessRelateFile businessRelateFile = new BusinessRelateFile();
            businessRelateFile.setFileId(reviewDto.getFileId());
            businessRelateFile.setBelongId(income.getId());
            businessRelateFile.setBelongType(BillingConstant.ERECEIVE_PAYMENT_VOUCHER);
            businessRelateFile.setFileType(FileTypeEnum.DISBURSEMENT_ENTRY.getCode());
            businessRelateFileBaseService.addBusinessRelateFiles(Collections.singletonList(businessRelateFile));
        }
        if ("USD".equals(reviewDto.getActualCurrency())) {
            ValidatorUtil.validator(ValidatorGroup.ValidatorType.SUBMIT, reviewDto);
        }
        income.setStatus(BillingConstant.ENTRY_STATUS_RECEIVED);
        income.setActualEntryDate(reviewDto.getActualEntryDate());
        income.setActualAmount(reviewDto.getActualAmount());
        income.setActualCurrency(reviewDto.getActualCurrency());
        income.setSettlementAmount(reviewDto.getSettlementAmount());
        income.setSettlementCurrency(reviewDto.getSettlementCurrency());
        income.setActualRetainedAmount(reviewDto.getActualRetainedAmount());
        income.setActualRetainedCurrency(reviewDto.getActualRetainedCurrency());
        income.setTransactionNumber(reviewDto.getTransactionNumber());
        income.setRemark(reviewDto.getRemark());
        PaymentCollectionOperate paymentCollectionOperate = paymentCollectionOperateService
                .getBusinessInfo(income.getId(), 1);
        if (paymentCollectionOperate != null) {
            paymentCollectionOperate.setReviewDate(LocalDateTime.now());
            paymentCollectionOperate.setReviewer(userNickName);
            paymentCollectionOperate.setReviewRemark(reviewDto.getRemark());
            paymentCollectionOperateService.updateById(paymentCollectionOperate);
        }
        billingIncomeService.updateById(income);
        BillingIncomeInfo billingIncomeInfo = billingIncomeInfoService.getBillingIncomeById(income.getId());
        if (billingIncomeInfo == null) {
            billingIncomeInfo = new BillingIncomeInfo();
            billingIncomeInfo.setAccountNumber(reviewDto.getAccountNumber());
            // billingIncomeInfo.setAccountName(reviewDto.getAccountName());
            billingIncomeInfo.setBillingIncomeId(income.getId());
            // billingIncomeInfo.setBankName(reviewDto.getBankName());
            // billingIncomeInfo.setOpeningBank(reviewDto.getOpeningBank());
            billingIncomeInfo.setVoucherNo(reviewDto.getVoucherNo());
            billingIncomeInfoService.save(billingIncomeInfo);
        } else {
            billingIncomeInfo.setAccountNumber(reviewDto.getAccountNumber());
            billingIncomeInfo.setVoucherNo(reviewDto.getVoucherNo());
            billingIncomeInfoService.updateById(billingIncomeInfo);
            if (StringUtils.isNotEmpty(billingIncomeInfo.getDetailIds())) {
                List<Long> detailIds = JSON.parseArray(billingIncomeInfo.getDetailIds(), Long.class);
                exportTaxRebateService.refundExportTaxAuditPassed(detailIds);
            }
        }
        separateAccountsService.saveSeparateAccounts(income, userNickName);
        if (BillingConstant.PAYMENT_TYPE_REPAYMENT.equals(income.getPaymentType())
                || BillingConstant.PAYMENT_TYPE_ADVANCES_ON_SALES.equals(income.getPaymentType())) {
            OrderIncomeAssociation orderIncomeAssociation = orderIncomeAssociationService
                    .getByBillingIncomeIdId(income.getId());
            if (orderIncomeAssociation != null) {
                String orderInfo = orderIncomeAssociation.getOrderInfo();
                if (StringUtils.isNotEmpty(orderInfo)) {
                    List<SalesOrderReceiveExtendDto> salesOrderInfo = JSON.parseArray(orderInfo,
                            SalesOrderReceiveExtendDto.class);
                    for (SalesOrderReceiveExtendDto salesOrderReceiveExtendDto : salesOrderInfo) {
                        SalesOrder salesOrder = iSalesOrderService
                                .getById(salesOrderReceiveExtendDto.getSalesOrderId());
                        int orderStatus = SaleOrderConstant.ORDER_STATUS_PARTIAL_COLLECTION;
                        if (salesOrder.getStatus().equals(SaleOrderConstant.ORDER_STATUS_REPAYMENT_UNDER_REVIEW)) {
                            orderStatus = SaleOrderConstant.ORDER_STATUS_RECEIVED;
                        }
                        iSalesOrderService.updateSalesOrderAndGoodsStatus(salesOrderReceiveExtendDto, orderStatus,
                                SaleOrderConstant.GOODS_STATUS_RECEIVED, 3);
                    }
                }
            }
        }
        if (BillingConstant.PAYMENT_TYPE_EXPORT_TAX_REFUND_SERVICE_FEE.equals(income.getPaymentType())) {
            ResponseResult<CustomerUserDto> customerUserRr = customerUserService
                    .getCustomerUser(String.valueOf(income.getCustomerUserId()));
            if (customerUserRr.getCode() != HttpStatus.SUCCESS || customerUserRr.getData() == null) {
                throw new ServiceException("获取客户信息异常", HttpStatus.BAD_REQUEST);
            }
            enterpriseBaseService.taxRebateServiceFeePayment(income.getCustomerUserId(),
                    customerUserRr.getData().getXtUid(), DateUtils.parseLocalDate2Date(reviewDto.getActualEntryDate()));
        }
        try {
            if (fileStorage != null) {
                filingDocService.newTaskBySalesOrderNo(income.getSaleOrderNo(), 2);
            }
        } catch (Exception e) {
            log.error("新增备案单证写入任务失败，sale_order_no={}", income.getSaleOrderNo());
            log.error("新增备案单证写入任务失败，异常信息={}", e.getMessage());
        }
        return true;
    }

    @Override
    public BillingIncomeDetailDto getBillingIncomeDetail(Long id) {
        BillingIncome income = billingIncomeService.getById(id);
        if (income == null) {
            throw new ServiceException("未找到该出入账申请记录");
        }
        BillingIncomeDetailDto detailDto = new BillingIncomeDetailDto();
        detailDto.setBillingIncome(income);
        PaymentCollectionOperate paymentCollectionOperate = paymentCollectionOperateService
                .getBusinessInfo(income.getId(), 1);
        detailDto.setPaymentCollectionOperate(paymentCollectionOperate);
        businessRelateFileBaseService.fillBizObjFiles(detailDto, income.getId(),
                BillingConstant.ERECEIVE_PAYMENT_VOUCHER, FileTypeEnum.DISBURSEMENT_ENTRY.getCode());
        // BillingIncomeInfo billingIncomeInfo = billingIncomeInfoService.getBillingIncomeById(id);
        // if (billingIncomeInfo != null) {
        // BankAccountDto bankAccountDto = new BankAccountDto();
        // bankAccountDto.setAccountNumber(billingIncomeInfo.getAccountNumber());
        // bankAccountDto.setAccountName(billingIncomeInfo.getAccountName());
        // bankAccountDto.setOpeningBank(billingIncomeInfo.getOpeningBank());
        // detailDto.setBankAccountDto(bankAccountDto);
        //
        BillingIncomeInfo billingIncomeInfo = billingIncomeInfoService.getBillingIncomeById(income.getId());
        if (billingIncomeInfo != null) {
            BankAccountDto bankAccountDto = new BankAccountDto();
            bankAccountDto.setAccountNumber(billingIncomeInfo.getAccountNumber());
            detailDto.setBankAccountDto(bankAccountDto);
            BillingIncomeInfoDto billingIncomeInfoDto = new BillingIncomeInfoDto();
            billingIncomeInfoDto.setVoucherNo(billingIncomeInfo.getVoucherNo());
            billingIncomeInfoDto.setDeclarationBatch(billingIncomeInfo.getDeclarationBatch());
            billingIncomeInfoDto.setDeclarationMonthYear(billingIncomeInfo.getDeclarationMonthYear());
            detailDto.setBillingIncomeInfo(billingIncomeInfoDto);
        }
        OrderIncomeAssociation incomeAssociation = orderIncomeAssociationService.getByBillingIncomeIdId(income.getId());
        if (incomeAssociation != null) {
            TradeRepaymentDto tradeRepaymentDto = new TradeRepaymentDto();
            tradeRepaymentDto.setRemark(incomeAssociation.getRemark());
            tradeRepaymentDto.setAccountNumber(incomeAssociation.getAccountNumber());
            tradeRepaymentDto.setExpectedPaymentDueDate(incomeAssociation.getExpectedPaymentDueDate());
            tradeRepaymentDto.setPromptReceivingCurrency(incomeAssociation.getPromptReceivingCurrency());
            String fileIds = incomeAssociation.getFileIds();
            if (StringUtils.isNotBlank(fileIds)) {
                List<Long> fileIdsList = JSON.parseArray(fileIds, Long.class);
                List<FileAbstractDto> attachment = new ArrayList<>();
                for (Long aLong : fileIdsList) {
                    TFileStorage fileStorages = fileStorageService.getFileStorageById(aLong);
                    attachment.add(new FileAbstractDto(fileStorages));
                }
                tradeRepaymentDto.setAttachment(attachment);
            }
            //
            if (StringUtils.isNotEmpty(incomeAssociation.getBusinessBatchNumber())) {
                List<OrderListInfoDto> listInfoDtos = orderReceivePaymentAssociationService
                        .queryByBusinessBatchNumber(incomeAssociation.getBusinessBatchNumber());
                for (OrderListInfoDto listInfoDto : listInfoDtos) {
                    listInfoDto.setExpectedPaymentDueDate(incomeAssociation.getExpectedPaymentDueDate());
                    if (listInfoDto.getFileId() != null) {
                        TFileStorage fileStorages = fileStorageService.getFileStorageById(listInfoDto.getFileId());
                        listInfoDto.setSupplementaryAgreementDocument(new FileAbstractDto(fileStorages));
                    }
                    String orderInfo = incomeAssociation.getOrderInfo();
                    if (StringUtils.isNotEmpty(orderInfo)) {
                        List<SalesOrderReceiveExtendDto> salesOrderInfo = JSON.parseArray(orderInfo,
                                SalesOrderReceiveExtendDto.class);
                        for (SalesOrderReceiveExtendDto salesOrderReceiveExtendDto : salesOrderInfo) {
                            SalesOrderGoods salesOrderGoods = iSalesOrderGoodsService
                                    .getMaxAmountByIds(salesOrderReceiveExtendDto.getSalesOrderGoodsIds());
                            if (salesOrderGoods != null) {
                                listInfoDto.setGoodsName(salesOrderGoods.getDeclarationName());
                            }
                        }
                    }
                }
            }
        }
        return detailDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean submitEntryDetail(BillingIncomeInfoDto billingIncomeInfoDto) {
        BillingIncome income = billingIncomeService.getById(billingIncomeInfoDto.getBillingIncomeId());
        if (income == null) {
            throw new ServiceException("未找到该出入账申请记录");
        }
        if (billingIncomeInfoDto.getFileId() != null) {
            TFileStorage fileStorage = fileStorageService.getFileStorageById(billingIncomeInfoDto.getFileId());
            if (fileStorage != null) {
                BusinessRelateFile businessRelateFile = new BusinessRelateFile();
                businessRelateFile.setFileId(billingIncomeInfoDto.getFileId());
                businessRelateFile.setBelongId(income.getId());
                businessRelateFile.setBelongType(BillingConstant.ERECEIVE_PAYMENT_VOUCHER);
                businessRelateFile.setFileType(FileTypeEnum.DISBURSEMENT_ENTRY.getCode());
                businessRelateFileBaseService.addBusinessRelateFiles(Collections.singletonList(businessRelateFile));
            }
        }
        BillingIncomeInfo billingIncomeInfo = billingIncomeInfoService.getBillingIncomeById(income.getId());
        if (billingIncomeInfo != null) {
            billingIncomeInfo.setVoucherNo(billingIncomeInfoDto.getVoucherNo());
            billingIncomeInfoService.updateById(billingIncomeInfo);
        }
        String userNickName = SecurityUtils.getUserNickName();
        PaymentCollectionOperate paymentCollectionOperate = new PaymentCollectionOperate(income.getId(), 11);
        paymentCollectionOperate.setReviewDate(LocalDateTime.now());
        paymentCollectionOperate.setReviewer(userNickName);
        paymentCollectionOperate.setReviewRemark(billingIncomeInfoDto.getRemark());
        paymentCollectionOperateService.save(paymentCollectionOperate);
        return true;
    }
}
