package com.inkasso.factoring.purchManagement.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.inkasso.adapter.exception.BusinessException;
import com.inkasso.adapter.util.CodeUtil;
import com.inkasso.adapter.util.CollectionUtil;
import com.inkasso.adapter.util.StringUtil;
import com.inkasso.adapter.web.LoginUserHolder;
import com.inkasso.auth.exception.ValidatorException;
import com.inkasso.factoring.biddingManagement.entity.vo.BiddingBasicInfoResultVo;
import com.inkasso.factoring.common.dict.impl.FileModuleDict;
import com.inkasso.factoring.common.entity.GridPage;
import com.inkasso.factoring.creditmanagement.entity.Enterprise;
import com.inkasso.factoring.creditmanagement.service.IEnterpriseService;
import com.inkasso.factoring.dict.service.DictionaryService;
import com.inkasso.factoring.file.entity.FileStorage;
import com.inkasso.factoring.file.service.FileStorageService;
import com.inkasso.factoring.purchManagement.dao.CPurchContractManagementMapper;
import com.inkasso.factoring.purchManagement.entity.*;
import com.inkasso.factoring.purchManagement.entity.vo.PurchContractCompletedVo;
import com.inkasso.factoring.purchManagement.entity.vo.PurchContractVo;
import com.inkasso.factoring.purchManagement.entity.vo.SearchGoods;
import com.inkasso.factoring.purchManagement.service.*;
import com.inkasso.factoring.salesManagement.entity.*;
import com.inkasso.factoring.salesManagement.entity.vo.SalesContractBasicVo;
import com.inkasso.factoring.salesManagement.service.*;
import com.inkasso.factoring.tradingPlatform.entity.Platform;
import com.inkasso.factoring.tradingPlatform.service.ITradingPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 采购合同管理表 服务实现类
 * </p>
 *
 * @author yafan
 * @since 2023-12-02
 */
@Service
public class CPurchContractManagementServiceImpl extends ServiceImpl<CPurchContractManagementMapper, CPurchContractManagement>
        implements ICPurchContractManagementService {

    @Autowired
    private ICPurchContractBasicInfoService purchContractBasicInfoService;
    @Autowired
    private ICPurchContractRetentionInfoService purchContractRetentionInfoService;
    @Autowired
    private ICPurchContractPriceRuleService purchContractPriceRuleService;
    @Autowired
    private ICPurchContractSettlePaymentService purchContractSettlePaymentService;
    @Autowired
    private ICPurchContractBuyerSellerService purchContractBuyerSellerService;
    @Autowired
    private ICPurchContractGoodsInfoService purchContractGoodsInfoService;
    @Autowired
    private ICSalesContractManagementService salesContractService;
    @Autowired
    private ICSalesContractBasicInfoService salesContractBasicInfoService;
    @Autowired
    private ISalesContractApprovalService salesContractApprovalService;
    @Autowired
    private ISalesContractRetentionInfoService salesContractRetentionInfoService;
    @Autowired
    private IEnterpriseService enterpriseService;
    @Autowired
    private ITradingPlatformService platformService;
    @Autowired
    private DictionaryService dictionaryService;
    @Value("${trade.purchContractEnterUrl}")
    private String purchContractEnterUrl;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${trade.purchContractSelectGoodsUrl}")
    private String purchContractSelectGoodsUrl;
    @Value("${trade.getAllPurchSignFileUrl}")
    private String getAllPurchSignFileUrl;
    @Autowired
    private ICSalesContractSupplementGoodsInfoService supplementGoodsInfoService;
    @Autowired
    private ICSalesContractGoodsInfoService salesContractGoodsInfoService;
    @Autowired
    private FileStorageService fileStorageService;


    @Override
    public GridPage<CSalesContractSupplementGoodsInfo> selectGoods(SearchGoods searchGoods) {

        //获取销售合同管理信息
        CSalesContractManagement salesContractManagement = salesContractService.getByBusinessNumber(searchGoods.getBusinessNumber());
        CSalesContractBasicInfo basicInfo = salesContractBasicInfoService.getOne(new QueryWrapper<CSalesContractBasicInfo>()
                .eq("c_sales_contract_management_id", salesContractManagement.getId()));
        searchGoods.setSalesContractBasicInfoId(basicInfo.getId());

        //查询货物信息
        Page<CSalesContractSupplementGoodsInfo> page = PageHelper.startPage(searchGoods.getPage(), searchGoods.getRows());
        List<CSalesContractSupplementGoodsInfo> goodsInfos = supplementGoodsInfoService.getGoodsInfosWithSupplementGoods(salesContractManagement.getId(), basicInfo.getId());

        return new GridPage<>(searchGoods.getRows(), searchGoods.getPage(), page.getTotal(), goodsInfos);

    }

    @Override
    public List<CPurchContractGoodsInfo> calculateGoods(SearchGoods searchGoods) {
        CPurchContractPriceRule priceRule = searchGoods.getPriceRule();
        if (priceRule == null) {
            CPurchContractBasicInfo purch = purchContractBasicInfoService.getById(searchGoods.getBusinessKey());
            priceRule = purchContractPriceRuleService
                    .lambdaQuery().eq(CPurchContractPriceRule::getPurchContractBasicInfoId, purch.getId()).one();
        }
        List<CSalesContractSupplementGoodsInfo> salesGoods = searchGoods.getSalesContractSupplementGoodsInfos();
        CPurchContractPriceRule finalPriceRule = priceRule;
        List<CPurchContractGoodsInfo> purchContractGoodsInfos = salesGoods.stream().map(r -> {
            if (r.getSupplement()) {
                CSalesContractSupplementGoodsInfo salesContractSupplementGoodsInfo = supplementGoodsInfoService.getById(r.getId());
                CPurchContractGoodsInfo purchContractGoodsInfo = new CPurchContractGoodsInfo();
                if (salesContractSupplementGoodsInfo.getClearPrice() == 1) {
                    if (finalPriceRule.getAccrualMarginCalcMethod() == 1) {
                        //当（采购合同管理->采购合同录入->价格规则->利差计算方式）为 固定差额 时，则采购单价=销售单价- 差额（采购合同管理->采购合同录入->价格规则->差额）
                        BigDecimal differAmount = finalPriceRule.getDifferAmount();
                        if (differAmount == null) {
                            purchContractGoodsInfo.setPrice("不明确");
                        } else {
                            BigDecimal salesPrice = new BigDecimal(salesContractSupplementGoodsInfo.getSalesPrice());
                            BigDecimal price = salesPrice.subtract(differAmount);
                            purchContractGoodsInfo.setPrice(String.valueOf(price));
                        }
                    } else if (finalPriceRule.getAccrualMarginCalcMethod() == 0) {
                        //当（采购合同管理->采购合同录入->价格规则->利差计算方式）为 固定利率 时，则采购单价=销售单价-销售单价*(月利率)*（预估保理融资期限/30），--（采购合同管理->采购合同录入->价格规则->预估保理融资期限）；
                        BigDecimal monthlyInterestRate = finalPriceRule.getMonthlyInterestRate();
                        Integer factoringFinanceDeadline = finalPriceRule.getFactoringFinanceDeadline();
                        if (monthlyInterestRate == null || factoringFinanceDeadline == null) {
                            throw new ValidatorException(CodeUtil.FAIL, "利差计算方式不明确！");
                        }
                        if (StringUtil.isNumeric(salesContractSupplementGoodsInfo.getSalesPrice())) {
                            BigDecimal salesPrice = new BigDecimal(salesContractSupplementGoodsInfo.getSalesPrice());
                            BigDecimal price = salesPrice.subtract(
                                            salesPrice
                                                    .multiply(monthlyInterestRate.divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP))
                                                    .multiply(BigDecimal.valueOf(factoringFinanceDeadline).divide(new BigDecimal(30), 6, RoundingMode.HALF_UP)))
                                    .setScale(4, RoundingMode.HALF_UP);
                            purchContractGoodsInfo.setPrice(String.valueOf(price));
                        } else {
                            purchContractGoodsInfo.setPrice("不明确");
                        }
                    }
                } else {
                    purchContractGoodsInfo.setPrice("不明确");
                }
                purchContractGoodsInfo.setId(salesContractSupplementGoodsInfo.getId());
                purchContractGoodsInfo.setGoodsName(salesContractSupplementGoodsInfo.getGoodsName());
                purchContractGoodsInfo.setGoodsFactory(salesContractSupplementGoodsInfo.getGoodsFactory());
                purchContractGoodsInfo.setModelNumber(salesContractSupplementGoodsInfo.getModelNumber());
                purchContractGoodsInfo.setUnits(salesContractSupplementGoodsInfo.getUnits());
                purchContractGoodsInfo.setQuantity(r.getQuantity());
                purchContractGoodsInfo.setRemark(salesContractSupplementGoodsInfo.getRemark());
                purchContractGoodsInfo.setSupplement(true);
                return purchContractGoodsInfo;
            } else {
                CSalesContractGoodsInfo salesContractGoodsInfo = salesContractGoodsInfoService.getById(r.getId());
                CPurchContractGoodsInfo purchContractGoodsInfo = new CPurchContractGoodsInfo();
                if (salesContractGoodsInfo.getClearPrice().equals(1)) {
                    if (finalPriceRule.getAccrualMarginCalcMethod() == 1) {
                        //当（采购合同管理->采购合同录入->价格规则->利差计算方式）为 固定差额 时，则采购单价=销售单价- 差额（采购合同管理->采购合同录入->价格规则->差额）
                        BigDecimal differAmount = finalPriceRule.getDifferAmount();
                        if (differAmount == null) {
                            purchContractGoodsInfo.setPrice("不明确");
                        } else {
                            BigDecimal salesPrice = new BigDecimal(salesContractGoodsInfo.getSalesPrice());
                            BigDecimal price = salesPrice.subtract(differAmount);
                            purchContractGoodsInfo.setPrice(String.valueOf(price));
                        }
                    } else if (finalPriceRule.getAccrualMarginCalcMethod() == 0) {
                        //当（采购合同管理->采购合同录入->价格规则->利差计算方式）为 固定利率 时，则采购单价=销售单价-销售单价*(月利率)*（预估保理融资期限/30），--（采购合同管理->采购合同录入->价格规则->预估保理融资期限）；
                        BigDecimal monthlyInterestRate = finalPriceRule.getMonthlyInterestRate();
                        Integer factoringFinanceDeadline = finalPriceRule.getFactoringFinanceDeadline();
                        if (monthlyInterestRate == null || factoringFinanceDeadline == null) {
                            throw new ValidatorException(CodeUtil.FAIL, "利差计算方式不明确！");
                        }
                        if (StringUtil.isNumeric(salesContractGoodsInfo.getSalesPrice())) {
                            BigDecimal salesPrice = new BigDecimal(salesContractGoodsInfo.getSalesPrice());
                            BigDecimal price = salesPrice.subtract(
                                            salesPrice
                                                    .multiply(monthlyInterestRate.divide(new BigDecimal("100"), 6, RoundingMode.HALF_UP))
                                                    .multiply(BigDecimal.valueOf(factoringFinanceDeadline).divide(new BigDecimal(30), 6, RoundingMode.HALF_UP)))
                                    .setScale(4, RoundingMode.HALF_UP);
                            purchContractGoodsInfo.setPrice(String.valueOf(price));
                        } else {
                            purchContractGoodsInfo.setPrice("不明确");
                        }
                    }
                } else {
                    purchContractGoodsInfo.setPrice("不明确");
                }
                purchContractGoodsInfo.setId(salesContractGoodsInfo.getId());
                purchContractGoodsInfo.setGoodsName(salesContractGoodsInfo.getGoodsName());
                purchContractGoodsInfo.setGoodsFactory(salesContractGoodsInfo.getGoodsFactory());
                purchContractGoodsInfo.setModelNumber(salesContractGoodsInfo.getModelNumber());
                purchContractGoodsInfo.setUnits(salesContractGoodsInfo.getUnits());
                purchContractGoodsInfo.setQuantity(r.getQuantity());
                purchContractGoodsInfo.setRemark(salesContractGoodsInfo.getRemark());
                purchContractGoodsInfo.setSupplement(false);
                return purchContractGoodsInfo;
            }
        }).collect(Collectors.toList());
        return purchContractGoodsInfos;
    }


    @Override
    public void doAdd(PurchContractVo purchContractVo) {

        try {
            restTemplate.postForObject(purchContractEnterUrl, purchContractVo, String.class);
        } catch (Exception e) {
            String result = e.getMessage().substring(7, e.getMessage().length() - 1);
            JSONObject jsonObject = new JSONObject(result);
            throw new BusinessException(CodeUtil.FAIL, jsonObject.get("msg").toString());
        }

    }

    @Override
    public PurchContractVo add(Long id) {

        PurchContractVo purchContractVo = new PurchContractVo();
        CPurchContractManagement purchContractManagement = getById(id);
        if (purchContractManagement != null && purchContractManagement.getId() != null) {

            SalesContractBasicVo salesContractBasicVo = salesContractService
                    .getCompletedSalesByBusinessNumber(purchContractManagement.getBusinessNumber());
            purchContractVo.setBasicInfo(salesContractBasicVo);

            //获取最新的采购合同信息
            CPurchContractBasicInfo purch = purchContractBasicInfoService
                    .lambdaQuery().eq(CPurchContractBasicInfo::getPurchContractManagementId,purchContractManagement.getId()).one();

            //根据采购合同获取其他信息
            if (purch != null && purch.getId() != null) {
                purchContractVo.setPurchContractBasicInfo(purch);
                //获取质保金
                purchContractVo.setPurchContractRetentionInfo(purchContractRetentionInfoService.getOne(new QueryWrapper<CPurchContractRetentionInfo>()
                        .eq("c_purch_contract_basic_info_id", purch.getId())));
                //结算与付款
                purchContractVo.setPurchContractSettlePayment(purchContractSettlePaymentService.getOne(new QueryWrapper<CPurchContractSettlePayment>()
                        .eq("c_purch_contract_basic_info_id", purch.getId())));
                //获取价格规则
                purchContractVo.setPurchContractPriceRule(purchContractPriceRuleService.getOne(new QueryWrapper<CPurchContractPriceRule>()
                        .eq("c_purch_contract_basic_info_id", purch.getId())));
                //获取货物信息
                List<CPurchContractGoodsInfo> purchGoodsList = purchContractGoodsInfoService.list(new QueryWrapper<CPurchContractGoodsInfo>()
                        .eq("c_purch_contract_basic_info_id", purch.getId()));
                purchContractVo.setPurchContractGoodsInfoList(purchGoodsList);
                //获取供应商发货人
                purchContractVo.setPurchContractBuyerSellerList(purchContractBuyerSellerService.lambdaQuery()
                        .eq(CPurchContractBuyerSeller::getPurchContractBasicInfoId, purch.getId())
                        .eq(CPurchContractBuyerSeller::getBuyerOrSeller, 2).list());

            }

        }
        purchContractVo.setBusinessKey(id);

        return purchContractVo;
    }

    @Override
    public CPurchContractRetentionInfo getRetentionByBusinessNumber(String businessNumber) {

        if (businessNumber == null) {
            throw new ValidatorException(CodeUtil.FAIL, "业务编号不能为空！");
        }

        CPurchContractRetentionInfo purchContractRetentionInfo = new CPurchContractRetentionInfo();

        //销售合同基础信息表
        CSalesContractManagement salesContractManagement = salesContractService.lambdaQuery()
                .eq(CSalesContractManagement::getBusinessNumber, businessNumber).orderByDesc(CSalesContractManagement::getGmtCreate)
                .last("limit 1                                                                                                                                 ").one();
        if (salesContractManagement == null) {
            throw new BusinessException(CodeUtil.FAIL, "销售合同主信息为空！");
        }
        CSalesContractBasicInfo salesContractBasicInfo = salesContractBasicInfoService
                .lambdaQuery().eq(CSalesContractBasicInfo::getcSalesContractManagementId, salesContractManagement.getId()).one();
        //销售合同审核信息表
        if (salesContractBasicInfo != null) {
            SalesContractApproval salesApproval = salesContractApprovalService.getOne(new QueryWrapper<SalesContractApproval>()
                    .eq("c_sales_contract_basic_info_id", salesContractBasicInfo.getId())
                    .orderByDesc("gmt_create")
                    .last("limit 1"));
            //质保金信息
            SalesContractRetentionInfo salesContractRetentionInfo = salesContractRetentionInfoService
                    .getOne(new QueryWrapper<SalesContractRetentionInfo>()
                            .eq("sales_contract_approval_id", salesApproval.getId()));
            if (salesContractRetentionInfo != null) {
                BeanUtil.copyProperties(salesContractRetentionInfo, purchContractRetentionInfo, "id");
            }
        }

        return purchContractRetentionInfo;
    }

    @Override
    public PurchContractCompletedVo getCompletedPurchContractByBusinessNumber(String businessNumber) {
        PurchContractCompletedVo purchContractCompletedVo = baseMapper.getCompletedPurchContractByBusinessNumber(LoginUserHolder.get().getId(), businessNumber);
        if (purchContractCompletedVo != null) {
            if (purchContractCompletedVo.getCoreEnterpriseId() != null) {
                Enterprise coreEnterprise = enterpriseService.getById(purchContractCompletedVo.getCoreEnterpriseId());
                if (coreEnterprise != null) {
                    purchContractCompletedVo.setCoreEnterpriseName(coreEnterprise.getCorporateName());
                }
            }
            if (purchContractCompletedVo.getMainEnterpriseId() != null) {
                Enterprise mainEnterprise = enterpriseService.getById(purchContractCompletedVo.getMainEnterpriseId());
                if (mainEnterprise != null) {
                    purchContractCompletedVo.setMainEnterpriseName(mainEnterprise.getCorporateName());
                }
            }
            if (purchContractCompletedVo.getPlatformId() != null) {
                Platform platform = platformService.getById(purchContractCompletedVo.getPlatformId());
                if (platform != null) {
                    purchContractCompletedVo.setPlatformName(platform.getPlatformName());
                }
            }
            //经办人（供应商）
            CPurchContractBuyerSeller cPurchContractBuyerSeller = purchContractBuyerSellerService.getOne(new QueryWrapper<CPurchContractBuyerSeller>().eq("c_purch_contract_basic_info_id", purchContractCompletedVo.getcPurchContractBasicInfoId()).orderByDesc("gmt_modified")
                    .last("limit 1"));
            purchContractCompletedVo.setOperatorSupplier(cPurchContractBuyerSeller.getName());
        }
        return purchContractCompletedVo;
    }

    @Override
    public GridPage<CPurchContractBasicInfo> list(SearchSalesBasic searchSalesBasic) {

        searchSalesBasic.setUserId(LoginUserHolder.get().getId());
        Page<BiddingBasicInfoResultVo> page = PageHelper.startPage(searchSalesBasic.getPage(), searchSalesBasic.getRows());
        List<CPurchContractBasicInfo> list = baseMapper.findBySearch(searchSalesBasic);
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(purch -> {
                purch.setStatus(dictionaryService.getByCode(purch.getStatus()).getName());
            });
        }

        return new GridPage<>(searchSalesBasic.getRows(), searchSalesBasic.getPage(), page.getTotal(), list);
    }

    @Override
    public void downloadFile(Long id, HttpServletResponse response) {
        JSONObject jsonObject = restTemplate.getForObject(getAllPurchSignFileUrl + "?id=" + id, JSONObject.class);
        if (!jsonObject.get("code").equals("200")) {
            throw new BusinessException(CodeUtil.FAIL, "未查询到文件！");
        }
        String data = jsonObject.get("data").toString();
        List<FileStorage> fileStorageList = JSONArray.parseArray(data, FileStorage.class);

        fileStorageService.downloadZipFile(fileStorageList, FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SIGN_FILE.getCname(),response);

    }
}
