package com.fjhx.sale.service.statement.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fjhx.account.entity.account.po.AccountPayment;
import com.fjhx.account.entity.account.po.AccountRequestFundsDetail;
import com.fjhx.account.entity.account.po.AccountRunningWater;
import com.fjhx.account.entity.account.vo.AccountRequestFundsDetailVo;
import com.fjhx.account.entity.tax.po.TaxRefundDetails;
import com.fjhx.account.service.account.AccountPaymentService;
import com.fjhx.account.service.account.AccountRequestFundsDetailService;
import com.fjhx.account.service.account.AccountRequestFundsService;
import com.fjhx.account.service.account.AccountRunningWaterService;
import com.fjhx.account.service.tax.TaxRefundDetailsService;
import com.fjhx.common.entity.currency.po.CurrencyRate;
import com.fjhx.common.enums.FlowStatusEnum1;
import com.fjhx.common.service.currency.CurrencyRateService;
import com.fjhx.customer.service.customer.CustomerService;
import com.fjhx.purchase.entity.pay.po.Pay;
import com.fjhx.purchase.entity.purchase.enums.PurchaseStatusEnum;
import com.fjhx.purchase.entity.purchase.po.Purchase;
import com.fjhx.purchase.service.pay.PayDetailService;
import com.fjhx.purchase.service.purchase.PurchaseDetailService;
import com.fjhx.purchase.service.purchase.PurchaseService;
import com.fjhx.sale.entity.claim.po.ClaimContract;
import com.fjhx.sale.entity.contract.bo.ContractCurrencyRate;
import com.fjhx.sale.entity.contract.po.Contract;
import com.fjhx.sale.entity.purchase.po.EhsdPurchase;
import com.fjhx.sale.entity.statement.dto.ProfitSettlementDto;
import com.fjhx.sale.entity.statement.vo.ProfitSettlementVo;
import com.fjhx.sale.service.claim.ClaimContractService;
import com.fjhx.sale.service.claim.ClaimService;
import com.fjhx.sale.service.contract.ContractService;
import com.fjhx.sale.service.statement.SaleStatementService;
import com.github.pagehelper.util.StringUtil;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SaleStatementServiceImpl implements SaleStatementService {

    @Autowired
    private ContractService contractService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private CurrencyRateService currencyRateService;

    @Autowired
    private TaxRefundDetailsService taxRefundDetailsService;

    @Autowired
    private ClaimContractService claimContractService;

    @Autowired
    private AccountRunningWaterService accountRunningWaterService;

    @Autowired
    private PayDetailService payDetailService;

    @Autowired
    private ClaimService claimService;

    @Autowired
    private PurchaseDetailService purchaseDetailService;

    @Autowired
    private PurchaseService purchaseService;

    @Autowired
    private AccountRequestFundsDetailService accountRequestFundsDetailService;
    @Autowired
    private AccountRequestFundsService accountRequestFundsService;
    @Autowired
    private AccountPaymentService accountPaymentService;

    @Override
    public Page<ProfitSettlementVo> getProfitSettlement(ProfitSettlementDto dto) {

        Page<Contract> contractPage = getContractPage(dto);
        List<Contract> records = contractPage.getRecords();
        if (records.size() == 0) {
            return new Page<>();
        }
        // 转换为vo
        List<ProfitSettlementVo> list = createResultList(records);
        // 赋值业务员名称
        UserUtil.assignmentNickName(list, ProfitSettlementVo::getUserId, ProfitSettlementVo::setUserName);
        // 赋值客户名称
        customerService.attributeAssign(list, ProfitSettlementVo::getCustomerId, (item, customer) -> {
            item.setCustomerName(customer.getName());
        });
        // 获取默认税率
        Map<String, BigDecimal> defaultRateMap = new HashMap<>();

        // 获取税率明细
        Map<Long, Map<String, BigDecimal>> detailsRateMap = getDetailsRateMap(records, defaultRateMap);

        //赋值合同到账金额、退税金额、采购金额
        setContractArrivalAndRefundMoney(list);

//        // 赋值采购合同金额和支付货款
//        setPurchaseAmountAndPayForGoods(list, detailsRateMap);

        // 计算
        calculation(list);

        // 转page
        return toPage(contractPage, list);
    }

    /**
     * 获取单条合同汇率
     */
    private Map<Long, Map<String, BigDecimal>> getDetailsRateMap(
            List<Contract> records, Map<String, BigDecimal> defaultRateMap) {

        HashMap<Long, Map<String, BigDecimal>> result = new HashMap<>();

        for (Contract record : records) {

            Map<String, BigDecimal> map;

            // 明细数据税率
            String currencyRateJson = record.getCurrencyRateJson();
            if (!StrUtil.isBlank(currencyRateJson)) {
                List<ContractCurrencyRate> contractCurrencyRates = JSON.parseArray(currencyRateJson, ContractCurrencyRate.class);

                map = contractCurrencyRates.stream()
                        .collect(Collectors.toMap(ContractCurrencyRate::getType, ContractCurrencyRate::getRate));

                defaultRateMap.forEach(map::putIfAbsent);

            } else {
//                map = new HashMap<>(defaultRateMap);
                map = new HashMap<>();
                map.put(record.getCurrency(), record.getRate());
            }

            result.put(record.getId(), map);
        }

        return result;
    }

    /**
     * 获取合同分页
     */
    private Page<Contract> getContractPage(ProfitSettlementDto dto) {

        Page<Contract> page = contractService.page(dto.getPage(), q -> q
                .orderByDesc(Contract::getCreateTime)
                .between(Contract::getStatus, FlowStatusEnum1.PASS.getKey(), FlowStatusEnum1.UPDATE.getKey() - 1)
                .eq(ObjectUtil.isNotEmpty(dto.getSettlementStatus()), Contract::getSettlementStatus, dto.getSettlementStatus())
                .eq(ObjectUtil.isNotEmpty(dto.getUserId()), Contract::getCreateUser, dto.getUserId())
                .like(StringUtil.isNotEmpty(dto.getKeyword()),Contract::getCode,dto.getKeyword())
        );

        return page;
    }

    /**
     * 创建结果集list
     */
    private List<ProfitSettlementVo> createResultList(List<Contract> records) {

        return records.stream().map(item -> {
            ProfitSettlementVo profitSettlementVo = new ProfitSettlementVo();
            profitSettlementVo.setContractId(item.getId());
            profitSettlementVo.setContractCode(item.getCode());
            profitSettlementVo.setCustomerId(item.getBuyCorporationId());
            profitSettlementVo.setUserId(item.getCreateUser());
            profitSettlementVo.setContractAmount(item.getAmount());
            profitSettlementVo.setCurrency(item.getCurrency());
            profitSettlementVo.setRate(item.getRate());
            profitSettlementVo.setCurrencyRateJson(item.getCurrencyRateJson());
            profitSettlementVo.setSettlementStatus(item.getSettlementStatus());

            return profitSettlementVo;
        }).collect(Collectors.toList());

    }

    /**
     * 获取默认汇率
     */
    private Map<String, BigDecimal> getDefaultRateMap() {
        List<CurrencyRate> list = currencyRateService.list();
        return list.stream().collect(Collectors.toMap(CurrencyRate::getType, CurrencyRate::getRate));
    }

    /**
     * 赋值合同到账金额、退税金额、采购金额
     */
    private void setContractArrivalAndRefundMoney(List<ProfitSettlementVo> list) {

//        // 合同id
//        List<Long> contractIdList = list.stream().map(ProfitSettlementVo::getContractId).collect(Collectors.toList());
//
//        // 根据合同id获取到账认领明细列表
//        List<ClaimContract> claimContractList = claimContractService.list(q ->
//                q.in(ClaimContract::getContractId, contractIdList));
//
//        if (claimContractList.size() == 0) {
//            return;
//        }
//
//        // 到账认领明细id列表
//        List<Long> claimIdList = claimContractList.stream()
//                .map(ClaimContract::getClaimId).distinct().collect(Collectors.toList());
//
//        // 到账认领列表
//        List<Claim> claimList = claimService.listByIds(claimIdList);
//
//        // 到账认领id 币种 map
//        Map<Long, String> claimIdCurrencyMap = claimList.stream()
//                .collect(Collectors.toMap(BaseIdPo::getId, Claim::getCurrency));
//
//        // 合同id 到账认领明细列表 map
//        Map<Long, List<ClaimContract>> contractIdClaimContractListMap =
//                claimContractList.stream().collect(Collectors.groupingBy(ClaimContract::getContractId));
//
//        for (ProfitSettlementVo profitSettlementVo : list) {
//
//            // 合同id
//            Long contractId = profitSettlementVo.getContractId();
//
//            // 到账认领
//            List<ClaimContract> itemClaimContractList = contractIdClaimContractListMap.getOrDefault(contractId, new ArrayList<>());
//
//            // 汇率币种map
//            Map<String, BigDecimal> map = detailsRateMap.get(contractId);
//
//            BigDecimal contractArrival = itemClaimContractList.stream().map(claimContract -> {
//
//                // 根据到账认领id获取币种
//                String currency = claimIdCurrencyMap.get(claimContract.getClaimId());
//
//                // 根据币种获取汇率
//                BigDecimal rate = map.getOrDefault(currency, BigDecimal.ONE);
//
//                // 获取认领金额
//                BigDecimal money = claimContract.getMoney();
//
//                // 返回兑人民币后金额
//                return rate.multiply(money);
//
//            }).reduce(BigDecimal.ZERO, BigDecimal::add);
//
//            profitSettlementVo.setContractArrival(contractArrival);
//
//        }
        // 合同id
        List<Long> contractIdList = list.stream().map(ProfitSettlementVo::getContractId).collect(Collectors.toList());
        //通过合同ID查询到账认领合同的数据
        List<ClaimContract> claimContractList = claimContractService.getListByContractIds(contractIdList);
        Map<Long, List<ClaimContract>> claimContractMap = claimContractList.stream().collect(Collectors.groupingBy(ClaimContract::getContractId));

        //通过合同ID查询到退税数据
        List<TaxRefundDetails> refundDetails = taxRefundDetailsService.getSumMoneyByContractIds(contractIdList);
        Map<Long, List<TaxRefundDetails>> refundDetailsMap = refundDetails.stream().collect(Collectors.groupingBy(TaxRefundDetails::getContractId));

        //通过合同IDS查询出采购数据
        List<Purchase> purchaseList = purchaseService.list(q -> q.in(Purchase::getDataResourceId, contractIdList).ge(Purchase::getPurchaseStatus, PurchaseStatusEnum.PASS.getKey()).lt(Purchase::getPurchaseStatus, PurchaseStatusEnum.CENCELLATION.getKey()));
        Map<Long, List<Purchase>> purchaseMap = purchaseList.stream().collect(Collectors.groupingBy(Purchase::getDataResourceId));

        for (ProfitSettlementVo p : list) {
            if (StringUtil.isNotEmpty(p.getCurrencyRateJson())) {//取设置的汇率
                List<CurrencyRate> assignCurrencyRatesList = JSON.parseArray(p.getCurrencyRateJson(), CurrencyRate.class);
                Map<String, BigDecimal> assignCurrencyRatesMap = assignCurrencyRatesList.stream().collect(Collectors.toMap(CurrencyRate::getType, CurrencyRate::getRate));
                /**
                 * 处理到账金额
                 */
                List<ClaimContract> cList = claimContractMap.getOrDefault(p.getContractId(), null);
                if (CollectionUtils.isNotEmpty(cList)) {
                    BigDecimal contractArrival = cList.stream().map(claimContract -> {
                        //获取汇率
                        BigDecimal rate = assignCurrencyRatesMap.getOrDefault(claimContract.getCurrency(), BigDecimal.ONE);
                        // 获取认领金额
                        BigDecimal money = claimContract.getMoney();
                        // 返回兑人民币后金额
                        return rate.multiply(money);
                    }).reduce(BigDecimal.ZERO, BigDecimal::add);
                    p.setContractArrival(contractArrival);
                }
                /**
                 * 处理退税金额
                 */
                List<TaxRefundDetails> rList = refundDetailsMap.getOrDefault(p.getContractId(), null);
                if (CollectionUtils.isNotEmpty(rList)) {
                    BigDecimal taxReturnMoney = rList.stream().map(taxRefundDetails -> {
                        //获取汇率
                        BigDecimal rate = assignCurrencyRatesMap.getOrDefault(taxRefundDetails.getCurrency(), BigDecimal.ONE);
                        // 获取认领金额
                        BigDecimal money = taxRefundDetails.getAmount();
                        // 返回兑人民币后金额
                        return rate.multiply(money);
                    }).reduce(BigDecimal.ZERO, BigDecimal::add);
                    p.setTaxReturnMoney(taxReturnMoney);
                }
                /**
                 * 处理采购金额
                 */
                List<Purchase> pList = purchaseMap.getOrDefault(p.getContractId(), null);
                if (CollectionUtils.isNotEmpty(pList)) {

                    BigDecimal purchaseAmount = pList.stream().map(purchase -> {
                        //获取汇率
                        BigDecimal rate = assignCurrencyRatesMap.getOrDefault(purchase.getCurrency(), BigDecimal.ONE);
                        // 获取认领金额
                        BigDecimal money = purchase.getAmount();
                        // 返回兑人民币后金额
                        return rate.multiply(money);
                    }).reduce(BigDecimal.ZERO, BigDecimal::add);
                    p.setPurchaseAmount(purchaseAmount);

                    /**
                     * 处理支付款金额
                     */
                    List<Long> purchaseIds = pList.stream().map(Purchase::getId).collect(Collectors.toList());
                    List<Pay> payList = payDetailService.getSumMoney(purchaseIds);
                    if (CollectionUtils.isNotEmpty(payList)) {
                        BigDecimal payAmount = payList.stream().map(pay -> {
                            //获取汇率
                            BigDecimal rate = pay.getRate()==null?BigDecimal.ONE:pay.getRate();
                            // 获取金额
                            BigDecimal money = pay.getAmount()==null?BigDecimal.ZERO:pay.getAmount();
                            // 返回兑人民币后金额
                            return rate.multiply(money);
                        }).reduce(BigDecimal.ZERO, BigDecimal::add);
                        p.setPayForGoods(payAmount);
                    }
                }
                /**
                 * 其他收入金额
                 */
                List<AccountRequestFundsDetailVo> accountRequestFundsDetailVos = accountRequestFundsDetailService.getListByContractId(p.getContractId());
                if (CollectionUtils.isNotEmpty(accountRequestFundsDetailVos)) {
                    BigDecimal otherExpenses = accountRequestFundsDetailVos.stream().map(acc -> {
                        //获取汇率
                        BigDecimal rate = assignCurrencyRatesMap.getOrDefault(acc.getCurrency(), BigDecimal.ONE);
                        // 获取认领金额
                        BigDecimal money = acc.getAmount();
                        // 返回兑人民币后金额
                        return rate.multiply(money);
                    }).reduce(BigDecimal.ZERO, BigDecimal::add);
                    p.setOtherExpenses(otherExpenses);
                }
            } else {//取数据汇率
                /**
                 * 处理到账金额
                 */
                List<ClaimContract> cList = claimContractMap.getOrDefault(p.getContractId(), new ArrayList<>());
                List<Long> warterIds = cList.stream().distinct().map(ClaimContract::getBusinessId).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(warterIds)) {
                    //查出流水
                    List<AccountRunningWater> accountRunningWaterList = accountRunningWaterService.list(Wrappers.<AccountRunningWater>query().lambda().in(AccountRunningWater::getId, warterIds));
                    Map<Long, BigDecimal> waterMap = accountRunningWaterList.stream().collect(Collectors.toMap(AccountRunningWater::getId, AccountRunningWater::getRate));
                    BigDecimal contractArrival = cList.stream().map(claimContract -> {
                        //获取汇率
                        BigDecimal rate = waterMap.getOrDefault(claimContract.getBusinessId(), BigDecimal.ONE);
                        // 获取金额
                        BigDecimal money = claimContract.getMoney();
                        // 返回兑人民币后金额
                        return rate.multiply(money);
                    }).reduce(BigDecimal.ZERO, BigDecimal::add);
                    p.setContractArrival(contractArrival);
                }
                /**
                 * 处理退税金额
                 */
                List<TaxRefundDetails> rList = refundDetailsMap.getOrDefault(p.getContractId(), null);
                if (CollectionUtils.isNotEmpty(rList)) {
                    BigDecimal taxReturnMoney = rList.stream().map(taxRefundDetails -> {
                        //获取汇率
                        BigDecimal rate = taxRefundDetails.getRate();
                        // 获取认领金额
                        BigDecimal money = taxRefundDetails.getAmount();
                        // 返回兑人民币后金额
                        return rate.multiply(money);
                    }).reduce(BigDecimal.ZERO, BigDecimal::add);
                    p.setTaxReturnMoney(taxReturnMoney);
                }
                /**
                 * 处理采购金额
                 */
                List<Purchase> pList = purchaseMap.getOrDefault(p.getContractId(), null);

                if (CollectionUtils.isNotEmpty(pList)) {
                    BigDecimal purchaseAmount = pList.stream().map(purchase -> {
                        //获取汇率
                        BigDecimal rate = purchase.getRate() == null ? BigDecimal.ONE : purchase.getRate();
                        // 获取认领金额
                        BigDecimal money = purchase.getAmount() == null ? BigDecimal.ZERO : purchase.getAmount();
                        // 返回兑人民币后金额
                        return rate.multiply(money);
                    }).reduce(BigDecimal.ZERO, BigDecimal::add);
                    p.setPurchaseAmount(purchaseAmount);

                    /**
                     * 处理支付款金额
                     */
                    List<Long> purchaseIds = pList.stream().map(Purchase::getId).collect(Collectors.toList());
                    List<Pay> payList = payDetailService.getSumMoney(purchaseIds);
                    if (CollectionUtils.isNotEmpty(payList)) {
                        BigDecimal payAmount = payList.stream().map(pay -> {
                            //获取汇率
                            BigDecimal rate = pay.getRate()==null?BigDecimal.ONE:pay.getRate();
                            // 获取认领金额
                            BigDecimal money = pay.getAmount()==null?BigDecimal.ZERO:pay.getAmount();
                            // 返回兑人民币后金额
                            return rate.multiply(money);
                        }).reduce(BigDecimal.ZERO, BigDecimal::add);
                        p.setPayForGoods(payAmount);
                    }
                }
                /**
                 * 其他收入金额
                 */
                List<AccountRequestFundsDetailVo> accountRequestFundsDetailVos = accountRequestFundsDetailService.getListByContractId(p.getContractId());
                if (CollectionUtils.isNotEmpty(accountRequestFundsDetailVos)) {
                    BigDecimal otherExpenses = accountRequestFundsDetailVos.stream().map(acc -> {
                        //获取汇率
                        BigDecimal rate = acc.getRate() == null ? BigDecimal.ZERO : acc.getRate();
                        // 获取认领金额
                        BigDecimal money = acc.getAmount();
                        // 返回兑人民币后金额
                        return rate.multiply(money);
                    }).reduce(BigDecimal.ZERO, BigDecimal::add);
                    p.setOtherExpenses(otherExpenses);
                }
            }
        }
    }

    /**
     * 赋值采购合同金额和支付货款
     */
    private void setPurchaseAmountAndPayForGoods(
            List<ProfitSettlementVo> list, Map<Long, Map<String, BigDecimal>> detailsRateMap) {
//
//        // 合同id
//        List<Long> contractIdList = list.stream().map(ProfitSettlementVo::getContractId).collect(Collectors.toList());
//
//        List<Purchase> purchaseList = purchaseService.list(q -> q.in(Purchase::getDataResourceId, contractIdList));
//
//        Map<Long,List<Purchase>> purchaseMap = purchaseList.stream().collect(Collectors.groupingBy(Purchase::getDataResourceId));
//        if (purchaseList.size() == 0) {
//            purchaseList.forEach(item -> item.setAmount(BigDecimal.ZERO));
//            return;
//        }

//        List<Long> purchaseIdList = purchaseDetailList.stream().map(PurchaseDetail::getPurchaseId).collect(Collectors.toList());
//        List<Purchase> purchaseList = purchaseService.listByIds(purchaseIdList);

//        // 采购id 币种 map
//        Map<Long, String> purchaseIdCurrencyMap = purchaseList.stream()
//                .collect(Collectors.toMap(BaseIdPo::getId, Purchase::getCurrency));

//        // 合同id 申购单列表 map
//        Map<Long, List<PurchaseDetail>> contractIdPurchaseDetailListMap = purchaseDetailList.stream()
//                .collect(Collectors.groupingBy(PurchaseDetail::getDataResourceId));

//        for (ProfitSettlementVo profitSettlementVo : list) {
//
//            // 合同id
//            Long contractId = profitSettlementVo.getContractId();
//            List<Purchase> pList = purchaseMap.getOrDefault(contractId,null);
//
////            // 申购单
////            List<PurchaseDetail> itemPurchaseDetailList = contractIdPurchaseDetailListMap.getOrDefault(contractId, new ArrayList<>());
//
//            // 汇率币种map
//            Map<String, BigDecimal> map = detailsRateMap.getOrDefault(contractId, new HashMap<>());
//
//            BigDecimal purchaseAmount = itemPurchaseDetailList.stream().map(purchaseDetail -> {
//
//                // 根据申购单id获取币种
//                String currency = purchaseIdCurrencyMap.get(purchaseDetail.getPurchaseId());
//
//                // 根据币种获取汇率
//                BigDecimal rate = map.getOrDefault(currency, BigDecimal.ONE);
//
//                // 获取申购金额
//                BigDecimal money = purchaseDetail.getAmount();
//
//                // 返回兑人民币后金额
//                return rate.multiply(money);
//
//            }).reduce(BigDecimal.ZERO, BigDecimal::add);
//
//            profitSettlementVo.setPurchaseAmount(purchaseAmount);
//
//        }

    }

    /**
     * 计算
     */
    private void calculation(List<ProfitSettlementVo> list) {

        for (ProfitSettlementVo profitSettlementVo : list) {

            // 收入
            BigDecimal totalIncome = profitSettlementVo.getOtherIncome().add(profitSettlementVo.getContractArrival().add(profitSettlementVo.getTaxReturnMoney()));
            profitSettlementVo.setTotalIncome(totalIncome);

            // 支出
            BigDecimal totalExpenses = profitSettlementVo.getOtherExpenses().add(profitSettlementVo.getPayForGoods());
            profitSettlementVo.setTotalExpenses(totalExpenses);

            // 毛利
            BigDecimal grossProfit = totalIncome.subtract(totalExpenses);
            profitSettlementVo.setGrossProfit(grossProfit);

            if (totalIncome.equals(BigDecimal.ZERO)) {
                profitSettlementVo.setGrossProfitMargin(BigDecimal.ZERO);
            } else {
                profitSettlementVo.setGrossProfitMargin(
                        new BigDecimal("100").multiply(grossProfit).divide(totalIncome, 2, RoundingMode.HALF_UP)
                );
            }

        }

    }

    /**
     * 转page
     */
    private Page<ProfitSettlementVo> toPage(Page<Contract> contractPage, List<ProfitSettlementVo> list) {
        Page<ProfitSettlementVo> page = new Page<>();
        page.setTotal(contractPage.getTotal());
        page.setCurrent(contractPage.getCurrent());
        page.setPages(contractPage.getPages());
        page.setSize(contractPage.getSize());
        page.setRecords(list);

        return page;
    }


}
