/**
 * @filename:SeparateAccountsServiceImpl 2024-10-23
 * @project KJT v1.1.0 Copyright(c) 2024 wanglang Co. Ltd. All right reserved.
 */
package com.trade.admin.business.separateaccounts.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.trade.admin.business.payment.service.PaymentBasicService;
import com.trade.admin.business.separateaccounts.dto.IncomeInfoDto;
import com.trade.admin.business.separateaccounts.dto.SubmitSeparateAccountsDto;
import com.trade.admin.business.separateaccounts.service.BSeparateAccountsService;
import com.trade.admin.business.separateaccounts.vo.SeparateAccountsDetailVo;
import com.trade.admin.business.separateaccounts.vo.SeparateAccountsSubmitVo;
import com.trade.admin.finance.disbursement.service.impl.BBillingDisbursementServiceImpl;
import com.trade.admin.finance.paymentcollection.dto.BankAccountDto;
import com.trade.admin.system.security.utils.SecurityUtils;
import com.trade.common.core.page.GridPage;
import com.trade.common.exception.ServiceException;
import com.trade.common.utils.ConstantUtil;
import com.trade.common.utils.LoggerUtil;
import com.trade.common.utils.bean.BeanCopyUtils;
import com.trade.service.business.separateaccounts.domain.SeparateAccounts;
import com.trade.service.business.separateaccounts.domain.SeparateAccountsInfo;
import com.trade.service.business.separateaccounts.dto.SeparateAccountsSearchDto;
import com.trade.service.business.separateaccounts.service.SeparateAccountsInfoService;
import com.trade.service.business.separateaccounts.service.SeparateAccountsService;
import com.trade.service.business.separateaccounts.vo.SeparateAccountsPageVo;
import com.trade.service.filestorage.enums.FileTypeEnum;
import com.trade.service.filestorage.service.BusinessRelateFileBaseService;
import com.trade.service.finance.constant.BillingConstant;
import com.trade.service.finance.paymentcollection.domain.BillingIncome;
import com.trade.service.finance.paymentcollection.domain.BillingIncomeInfo;
import com.trade.service.finance.paymentcollection.domain.PaymentCollectionOperate;
import com.trade.service.finance.paymentcollection.service.BillingIncomeInfoService;
import com.trade.service.finance.paymentcollection.service.BillingIncomeService;
import com.trade.service.finance.paymentcollection.service.PaymentCollectionOperateService;
import com.trade.service.trade.salescontract.domain.ContractTerms;
import com.trade.service.trade.salescontract.domain.SalesContract;
import com.trade.service.trade.salescontract.service.ContractTermsService;
import com.trade.service.trade.salescontract.service.SalesContractService;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @Description:分账表服务实现
 * @version: v1.1.0
 * @author: wanglang
 */
@Service
public class BSeparateAccountsServiceImpl implements BSeparateAccountsService {

    private static final Logger log = LoggerUtil.logger(LoggerUtil.LogFileNameEnum.SERVICES_LOG);
    @Resource
    private PaymentCollectionOperateService paymentCollectionOperateService;
    @Resource
    private SeparateAccountsInfoService separateAccountsInfoService;
    @Resource
    private ContractTermsService contractTermsService;
    @Resource
    private SalesContractService salesContractService;
    @Resource
    private BillingIncomeService billingIncomeService;
    @Resource
    private BillingIncomeInfoService billingIncomeInfoService;
    @Resource
    private PaymentBasicService paymentBasicService;
    @Resource
    private SeparateAccountsService separateAccountsService;
    @Resource
    private BusinessRelateFileBaseService businessRelateFileBaseService;
    @Resource
    private BBillingDisbursementServiceImpl bBillingDisbursementService;

    @Override
    public boolean saveSeparateAccounts(BillingIncome income, String operator) {
        if (income == null) {
            return false;
        }
        if (BillingConstant.PAYMENT_TYPE_TECHNICAL_SERVICE_FEE.equals(income.getPaymentType())
                || BillingConstant.PAYMENT_TYPE_EXPORT_TAX_REFUND_SERVICE_FEE.equals(income.getPaymentType())) {
            return true;
        }
        SeparateAccounts separateAccounts = BeanCopyUtils.copy(income, SeparateAccounts.class);
        separateAccounts.setBillingIncomeId(income.getId());
        separateAccounts.setEntryDate(income.getActualEntryDate());
        separateAccounts.setStatus(BillingConstant.ENTRY_STATUS_UNCONFIRMED);
        separateAccounts.setEntryAmount(income.getActualAmount());
        separateAccounts.setEntryCurrency(income.getActualCurrency());
        separateAccounts.setId(null);
        separateAccountsService.save(separateAccounts);
        PaymentCollectionOperate paymentCollectionOperate = new PaymentCollectionOperate(separateAccounts.getId(), 3);
        paymentCollectionOperate.setApplicant(operator);
        paymentCollectionOperate.setApplyDate(LocalDateTime.now());
        paymentCollectionOperateService.save(paymentCollectionOperate);
        return true;
    }

    @Override
    public GridPage<SeparateAccountsPageVo> queryListByPage(SeparateAccountsSearchDto searchDto) {
        Page<SeparateAccountsPageVo> page = PageHelper.startPage(searchDto.getPage(), searchDto.getRows());
        List<SeparateAccountsPageVo> voList = separateAccountsService.selectByPage(searchDto);
        return new GridPage<>(searchDto.getPage(), searchDto.getRows(), page.getTotal(), voList);
    }

    @Override
    public SeparateAccounts querySeparateAccounts(Long id) {
        return separateAccountsService.getById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitSeparateAccounts(List<SubmitSeparateAccountsDto> separateAccountsDtos) {
        if (CollectionUtil.isEmpty(separateAccountsDtos)) {
            throw new ServiceException("请选择出分账信息");
        }
        SeparateAccounts separateAccounts = separateAccountsService.getById(separateAccountsDtos.get(0).getId());
        if (null == separateAccounts) {
            throw new ServiceException("未找到该出分账申请记录");
        }
        // 分账金额校验
        BigDecimal ledgerAmount = separateAccountsDtos.stream().filter(s -> s.getLedgerAmount() != null)
                .map(SubmitSeparateAccountsDto::getLedgerAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (ledgerAmount.compareTo(separateAccounts.getEntryAmount()) != 0) {
            throw new ServiceException("分账金额与入账实际金额不符");
        }
        String userNickName = SecurityUtils.getUserNickName();
        for (SubmitSeparateAccountsDto separateAccountsDto : separateAccountsDtos) {
            SeparateAccountsInfo separateAccountsInfo = BeanCopyUtils.copy(separateAccountsDto,
                    SeparateAccountsInfo.class);
            separateAccountsInfo.setSeparateAccountsId(separateAccounts.getId());
            separateAccountsInfo.setLedgerCurrency(separateAccounts.getEntryCurrency());
            separateAccountsInfoService.save(separateAccountsInfo);
            // paymentBasicService.savePaymentBasic(separateAccounts, separateAccountsInfo, userNickName);
            // 业务变更 直接生成出账记录
            bBillingDisbursementService.saveBillingDisbursement(separateAccounts, separateAccountsInfo, userNickName);
        }
        PaymentCollectionOperate paymentCollectionOperate = paymentCollectionOperateService
                .getBusinessInfo(separateAccounts.getId(), 3);
        if (paymentCollectionOperate != null) {
            paymentCollectionOperate.setReviewDate(LocalDateTime.now());
            paymentCollectionOperate.setReviewer(userNickName);
            paymentCollectionOperateService.updateById(paymentCollectionOperate);
        }
        return true;
    }

    @Override
    public SeparateAccountsSubmitVo querySubmitSeparateAccounts(Long id) {
        SeparateAccounts separateAccounts = querySeparateAccounts(id);
        if (null == separateAccounts) {
            throw new ServiceException("未找到该出分账申请记录");
        }
        SeparateAccountsSubmitVo separateAccountsSubmitVo = new SeparateAccountsSubmitVo();
        separateAccountsSubmitVo.setSeparateAccounts(separateAccounts);
        if (BillingConstant.PAYMENT_TYPE_TAX_REFUND.equals(separateAccounts.getPaymentType())) {
            SalesContract salesContract = salesContractService.getByContractNo(separateAccounts.getSalesContractNo(),
                    separateAccounts.getCustomerUserId());
            if (salesContract == null) {
                log.error("销售合同不存在,销售合同编号:{}", separateAccounts.getSalesContractNo());
                return separateAccountsSubmitVo;
            }
            ContractTerms contractTerms = contractTermsService.getByContractIdAndType(salesContract.getId(),
                    ConstantUtil.SALES_CONTRACT_NO_PREFIX);
            if (contractTerms == null) {
                log.error("销售合同条款不存在,销售合同编号:{}", separateAccounts.getSalesContractNo());
                return separateAccountsSubmitVo;
            }
            List<BankAccountDto> bankAccountDtos = new ArrayList<>();
            BankAccountDto bankAccountDto = new BankAccountDto();
            bankAccountDto.setAccountNumber(contractTerms.getAccountNumber());
            bankAccountDto.setAccountName(contractTerms.getAccountName());
            bankAccountDto.setOpeningBank(contractTerms.getOpeningBank());
            bankAccountDtos.add(bankAccountDto);
            separateAccountsSubmitVo.setBankAccountDtos(bankAccountDtos);
        }
        BillingIncome billingIncome = billingIncomeService.getById(separateAccounts.getBillingIncomeId());
        if (billingIncome != null) {
            IncomeInfoDto incomeInfoDto = new IncomeInfoDto();
            incomeInfoDto.setApplyAmount(billingIncome.getApplyAmount());
            incomeInfoDto.setApplyCurrency(billingIncome.getApplyCurrency());
            BillingIncomeInfo billingIncomeInfo = billingIncomeInfoService.getBillingIncomeById(billingIncome.getId());
            if (billingIncomeInfo != null) {
                incomeInfoDto.setAccountNumber(billingIncomeInfo.getAccountNumber());
                incomeInfoDto.setDeclarationMonthYear(billingIncomeInfo.getDeclarationMonthYear());
                incomeInfoDto.setVoucherNo(billingIncomeInfo.getVoucherNo());
                incomeInfoDto.setDeclarationBatch(billingIncomeInfo.getDeclarationBatch());
            }
            separateAccountsSubmitVo.setSeparateAccounts(separateAccounts);
            PaymentCollectionOperate paymentCollectionOperate = paymentCollectionOperateService
                    .getBusinessInfo(billingIncome.getId(), 1);
            if (paymentCollectionOperate != null) {
                incomeInfoDto.setReviewRemark(paymentCollectionOperate.getReviewRemark());
                incomeInfoDto.setReviewer(paymentCollectionOperate.getReviewer());
            }
            businessRelateFileBaseService.fillBizObjFiles(separateAccountsSubmitVo, billingIncome.getId(),
                    BillingConstant.ERECEIVE_PAYMENT_VOUCHER, FileTypeEnum.DISBURSEMENT_ENTRY.getCode());
            separateAccountsSubmitVo.setIncomeInfoDto(incomeInfoDto);
        }
        return separateAccountsSubmitVo;
    }

    @Override
    public SeparateAccountsDetailVo querySeparateAccountsDetail(Long id) {
        SeparateAccounts separateAccounts = querySeparateAccounts(id);
        if (null == separateAccounts) {
            return null;
        }
        SeparateAccountsDetailVo separateAccountsDetailVo = new SeparateAccountsDetailVo();
        separateAccountsDetailVo.setSeparateAccounts(separateAccounts);
        BillingIncome billingIncome = billingIncomeService.getById(separateAccounts.getBillingIncomeId());
        if (null != billingIncome) {
            separateAccountsDetailVo.setRemark(billingIncome.getRemark());
            IncomeInfoDto incomeInfoDto = new IncomeInfoDto();
            incomeInfoDto.setApplyAmount(billingIncome.getApplyAmount());
            incomeInfoDto.setApplyCurrency(billingIncome.getApplyCurrency());
            BillingIncomeInfo billingIncomeInfo = billingIncomeInfoService.getBillingIncomeById(billingIncome.getId());
            if (billingIncomeInfo != null) {
                incomeInfoDto.setAccountNumber(billingIncomeInfo.getAccountNumber());
                incomeInfoDto.setDeclarationMonthYear(billingIncomeInfo.getDeclarationMonthYear());
                incomeInfoDto.setVoucherNo(billingIncomeInfo.getVoucherNo());
                incomeInfoDto.setDeclarationBatch(billingIncomeInfo.getDeclarationBatch());
            }
            separateAccountsDetailVo.setSeparateAccounts(separateAccounts);
            PaymentCollectionOperate paymentCollectionOperate = paymentCollectionOperateService
                    .getBusinessInfo(billingIncome.getId(), 1);
            if (paymentCollectionOperate != null) {
                incomeInfoDto.setReviewRemark(paymentCollectionOperate.getReviewRemark());
                incomeInfoDto.setReviewer(paymentCollectionOperate.getReviewer());
            }
            businessRelateFileBaseService.fillBizObjFiles(separateAccountsDetailVo, billingIncome.getId(),
                    BillingConstant.ERECEIVE_PAYMENT_VOUCHER, FileTypeEnum.DISBURSEMENT_ENTRY.getCode());
            separateAccountsDetailVo.setIncomeInfoDto(incomeInfoDto);
        }
        separateAccountsDetailVo
                .setAccountsInfo(separateAccountsInfoService.queryBySeparateAccountsId(separateAccounts.getId()));
        separateAccountsDetailVo
                .setOtherInfo(paymentCollectionOperateService.getBusinessInfo(separateAccounts.getId(), 3));
        return separateAccountsDetailVo;
    }
}
