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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.utils.Assert;
import com.fjhx.item.entity.product.ProcessesBo;
import com.fjhx.item.entity.product.po.ProductInfo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.sale.entity.quotation.dto.QuotationEstimateDto;
import com.fjhx.sale.entity.quotation.po.QuotationEstimate;
import com.fjhx.sale.entity.quotation.po.QuotationProduct;
import com.fjhx.sale.entity.quotation.po.QuotationProductBom;
import com.fjhx.sale.entity.quotation.vo.QuotationEstimateVo;
import com.fjhx.sale.entity.quotation.vo.QuotationProductVo;
import com.fjhx.sale.entity.sale.po.SaleQuotation;
import com.fjhx.sale.entity.sale.vo.SaleQuotationVo;
import com.fjhx.sale.mapper.quotation.QuotationEstimateMapper;
import com.fjhx.sale.service.quotation.QuotationEstimateService;
import com.fjhx.sale.service.quotation.QuotationProductBomService;
import com.fjhx.sale.service.quotation.QuotationProductService;
import com.fjhx.sale.service.sale.SaleQuotationService;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.utils.SecurityUtils;
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.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * <p>
 * 报价评估 服务实现类
 * </p>
 * <p>
 * \ * @since 2024-02-04
 */
@Service
public class QuotationEstimateServiceImpl extends ServiceImpl<QuotationEstimateMapper, QuotationEstimate> implements QuotationEstimateService {

    private final QuotationProductBomService quotationProductBomService;
    private final QuotationProductService quotationProductService;
    private final ProductInfoService productInfoService;
    private final SaleQuotationService saleQuotationService;

    @Autowired
    public QuotationEstimateServiceImpl(QuotationProductBomService quotationProductBomService, QuotationProductService quotationProductService, ProductInfoService productInfoService, SaleQuotationService saleQuotationService) {
        this.quotationProductBomService = quotationProductBomService;
        this.quotationProductService = quotationProductService;
        this.productInfoService = productInfoService;
        this.saleQuotationService = saleQuotationService;
    }

    @Override
    public List<QuotationEstimateVo> detail(QuotationEstimateDto dto) {
        Long quotationProductId = dto.getQuotationProductId();
        Assert.notEmpty(quotationProductId, "报价明细id不能为空！");

        QuotationProduct quotationProduct = quotationProductService.getById(quotationProductId);
        Assert.notEmpty(quotationProduct, "查询不到报价明细信息！");

        Long technologyId = quotationProduct.getTechnologyId();

        //查询现有报价信息
        List<QuotationEstimate> quotationEstimateList = list(q -> q.eq(QuotationEstimate::getQuotationProductId, quotationProductId));
        List<QuotationEstimateVo> quotationEstimateVos = BeanUtil.copyToList(quotationEstimateList, QuotationEstimateVo.class);

        //没有现有数据回填报价明细信息
        if (ObjectUtil.isEmpty(quotationEstimateVos)) {
            quotationEstimateVos = new ArrayList<>();
            List<QuotationProductBom> list1 = quotationProductBomService.list(q -> q.eq(QuotationProductBom::getQuotationProductId, quotationProductId));

            List<Long> mIds = list1.stream().map(QuotationProductBom::getMaterialId).collect(Collectors.toList());
            Map<Long, ProductInfo> materialInfoMap = productInfoService.mapKEntity(ProductInfo::getId, q -> q.in(ProductInfo::getId, mIds));

            //获取产品BOM
            for (QuotationProductBom quotationProductBom : list1) {
                QuotationEstimateVo quotationEstimate = new QuotationEstimateVo();
                quotationEstimate.setQuotationProductId(quotationProductBom.getQuotationProductId());
                quotationEstimate.setProductId(quotationProductBom.getProductId());
                quotationEstimate.setMaterialId(quotationProductBom.getMaterialId());
                quotationEstimate.setType(quotationProductBom.getType());

                //赋值单价信息
                ProductInfo materialId = materialInfoMap.get(quotationProductBom.getMaterialId());
                if (ObjectUtil.isNotEmpty(materialId)) {
                    quotationEstimate.setPrice(materialId.getPrice());
                }

                //原材料不赋值数量
                if (ObjectUtil.notEqual(quotationProductBom.getType(), 1)) {
                    quotationEstimate.setQuantity(quotationProductBom.getQuantity());
                }

                quotationEstimateVos.add(quotationEstimate);
            }


            List<ProcessesBo> processesList = productInfoService.getProcessesByTechnologyId(technologyId);
            for (ProcessesBo processesBo : processesList) {
                QuotationEstimateVo quotationEstimate = new QuotationEstimateVo();
                quotationEstimate.setProcessesId(processesBo.getId());
                quotationEstimate.setCode(processesBo.getCode());
                quotationEstimate.setName(processesBo.getName());
                quotationEstimate.setPrice(processesBo.getCostPrice());
                quotationEstimate.setQuantity(BigDecimal.valueOf(1));
                quotationEstimate.setType(3);

                quotationEstimateVos.add(quotationEstimate);
            }
        }

        //赋值物料工序信息
        setEstimateInfo(quotationEstimateVos);


        return quotationEstimateVos;
    }

    private void setEstimateInfo(List<QuotationEstimateVo> quotationEstimateVos) {
        //赋值模具信息
        List<Long> moldIds = quotationEstimateVos.stream().map(QuotationEstimate::getMoldId).collect(Collectors.toList());
        List<QuotationEstimateVo> moldInfoList = baseMapper.getMoldInfoList(moldIds);
        Map<Long, String> moldMap = moldInfoList.stream().collect(Collectors.toMap(QuotationEstimateVo::getId, QuotationEstimateVo::getMoldName));
        for (QuotationEstimateVo quotationEstimateVo : quotationEstimateVos) {
            quotationEstimateVo.setMoldName(moldMap.get(quotationEstimateVo.getMoldId()));
        }

        //赋值物料信息
        productInfoService.attributeAssign(quotationEstimateVos, QuotationEstimateVo::getMaterialId, (detail, product) -> {
            detail.setMaterialLength(product.getLength());
            detail.setMaterialWidth(product.getWidth());
            detail.setMaterialHeight(product.getHeight());
            detail.setName(product.getName());
            detail.setCode(product.getCustomCode());
            detail.setMaterialColor(product.getColor());
        });

        //赋值工序信息
        List<ProcessesBo> processesList = baseMapper.getProductionProcessesList();
        Map<Long, ProcessesBo> collect = processesList.stream().collect(Collectors.toMap(ProcessesBo::getId, Function.identity()));
        for (QuotationEstimateVo quotationEstimateVo : quotationEstimateVos) {
            ProcessesBo processesBo = collect.get(quotationEstimateVo.getProcessesId());
            if (ObjectUtil.isNotEmpty(processesBo)) {
                quotationEstimateVo.setName(processesBo.getName());
                quotationEstimateVo.setCode(processesBo.getCode());
            }
        }
    }

    @Override
    public void addOrEdit(QuotationEstimateDto quotationEstimateDto) {
        Long quotationProductId = quotationEstimateDto.getQuotationProductId();
        Assert.notEmpty(quotationProductId, "报价明细id不能为空！");

        QuotationProduct quotationProduct = quotationProductService.getById(quotationProductId);
        Assert.notEmpty(quotationProduct, "查询不到报价明细信息！");

        List<QuotationEstimate> quotationEstimateList = quotationEstimateDto.getQuotationEstimateList();
        for (QuotationEstimate quotationEstimate : quotationEstimateList) {
            quotationEstimate.setQuotationId(quotationProduct.getSaleQuotationId());
        }

        //计算产品单价
        BigDecimal amount = quotationEstimateList.stream().map(QuotationEstimate::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal divide = amount.divide(quotationProduct.getQuantity(), 4, RoundingMode.HALF_UP);
        quotationProductService.update(q -> q
                .eq(QuotationProduct::getId, quotationProductId)
                .set(QuotationProduct::getProdPrice, divide)
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );

        for (QuotationEstimate quotationEstimate : quotationEstimateList) {
            quotationEstimate.setQuotationProductId(quotationProductId);
        }
        this.saveOrUpdateBatch(quotationEstimateList);
    }

    @Override
    public void submitQuotation(Long id) {
        List<QuotationEstimate> list = this.list(q -> q.eq(QuotationEstimate::getQuotationId, id));
        BigDecimal sumAmount = list.stream().map(QuotationEstimate::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);


        saleQuotationService.update(q -> q
                .eq(SaleQuotation::getId, id)
                .set(SaleQuotation::getQuotationStatus, 2)
                .set(SaleQuotation::getProdAmount, sumAmount)
                .set(SaleQuotation::getQuotationTime, new Date())
                .set(SaleQuotation::getUpdateTime, new Date())
                .set(SaleQuotation::getUpdateUser, SecurityUtils.getUserId())
        );
    }

    @Override
    public SaleQuotationVo printPdf(QuotationEstimateDto dto) {
        Long quotationId = dto.getQuotationId();
        SaleQuotationVo detail = saleQuotationService.detail(quotationId);

        //获取报价信息
        List<QuotationEstimate> quotationEstimateList = this.list(q -> q
                .eq(QuotationEstimate::getQuotationId, quotationId)
        );
        List<QuotationEstimateVo> quotationEstimateVos = BeanUtil.copyToList(quotationEstimateList, QuotationEstimateVo.class);

        //赋值物料工序信息
        setEstimateInfo(quotationEstimateVos);

        Map<Long, List<QuotationEstimateVo>> estimateMap = quotationEstimateVos.stream().collect(Collectors.groupingBy(QuotationEstimate::getQuotationProductId));


        List<QuotationProductVo> quotationProductList = detail.getQuotationProductList();
        for (QuotationProductVo quotationProduct : quotationProductList) {
            quotationProduct.setQuotationEstimateList(estimateMap.get(quotationProduct.getId()));
        }

        return detail;
    }

}
