package com.fjhx.mes.service.production.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.utils.Assert;
import com.fjhx.item.entity.product.po.ProductInfo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.mes.entity.production.dto.ProduceOrderDetailSelectDto;
import com.fjhx.mes.entity.production.dto.ProductionOrderDetailDto;
import com.fjhx.mes.entity.production.dto.ProductionTaskDetailDto;
import com.fjhx.mes.entity.production.po.ProductionOrder;
import com.fjhx.mes.entity.production.po.ProductionOrderDetail;
import com.fjhx.mes.entity.production.po.ProductionTaskProgress;
import com.fjhx.mes.entity.production.vo.ProductionOrderDetailVo;
import com.fjhx.mes.entity.production.vo.ProductionTaskProgressVo;
import com.fjhx.mes.mapper.production.ProduceOrderDetailMapper;
import com.fjhx.mes.mapper.production.ProductionTaskProgressMapper;
import com.fjhx.mes.service.production.ProduceOrderDetailService;
import com.fjhx.mes.service.production.ProduceOrderService;
import com.fjhx.sale.entity.contract.po.ContractProductBom;
import com.fjhx.sale.entity.contract.vo.ContractProductBomVo;
import com.fjhx.sale.service.contract.ContractProductBomService;
import com.fjhx.sale.service.contract.ContractProductService;
import com.fjhx.tenant.utils.DeptUstil;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.common.utils.wrapper.SqlField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * <p>
 * 生产订单明细 服务实现类
 * </p>
 *
 * @author
 * @since 2024-01-10
 */
@Service
public class ProduceOrderDetailServiceImpl extends ServiceImpl<ProduceOrderDetailMapper, ProductionOrderDetail> implements ProduceOrderDetailService {

    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private ProductionTaskProgressMapper productionTaskProgressMapper;
    @Autowired
    private ContractProductService contractProductService;
    @Autowired
    private ContractProductBomService contractProductBomService;
    @Autowired
    private ProduceOrderService produceOrderService;

    @Override
    public Page<ProductionOrderDetailVo> getPage(ProduceOrderDetailSelectDto dto) {
        IWrapper<ProductionOrderDetail> wrapper = getWrapper();

        //只显示投产的数据
        wrapper.isNotNull("po.produce_time");

        //生产状态
        wrapper.eq("pod", ProductionOrderDetail::getProduceStatus, dto.getProduceStatus());
        //交期-时间范围过滤
        wrapper.ge("po", ProductionOrder::getDeliveryPeriod, dto.getStaDeliveryPeriod());
        wrapper.le("po", ProductionOrder::getDeliveryPeriod, dto.getEndDeliveryPeriod());
        //下单时间（创建时间）-时间范围过滤
        wrapper.ge("po", ProductionOrder::getCreateTime, dto.getBeginTime());
        wrapper.le("po", ProductionOrder::getCreateTime, dto.getEndTime());
        //关键字
        if (ObjectUtil.isNotEmpty(dto.getKeyword())) {
            wrapper.and(q -> q
                    .like("po.code", dto.getKeyword())
                    .or().apply("po.contract_id in (SELECT DISTINCT c.id FROM contract c JOIN customer cu ON c.buy_corporation_id = cu.id JOIN sys_user su ON cu.user_id = su.user_id WHERE su.nick_name LIKE CONCAT('%', {0},'%'))", dto.getKeyword())
            );
            wrapper.keyword(dto.getKeyword(), new SqlField("po", ProductionOrder::getCode));
        }

        wrapper.orderByDesc("po", ProductionOrder::getCreateTime);
        wrapper.orderByDesc("pod", ProductionOrderDetail::getId);

        //权限过滤：生产订单-子公司看自己的,总公司看全部
        Long companyId = SecurityUtils.getCompanyId();
        if (!Objects.equals(companyId, 100L)) {
            wrapper.eq("po", ProductionOrder::getCompanyId, companyId);
        } else {
            wrapper.eq("po", ProductionOrder::getCompanyId, dto.getCompanyId());
        }

        //是否逾期过滤
        if (ObjectUtil.isNotEmpty(dto.getIsOverdue())) {
            wrapper.eq("IF(IFNULL(po.finish_time,NOW())>po.delivery_period,1,0)", dto.getIsOverdue());
        }

        Page<ProductionOrderDetailVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<ProductionOrderDetailVo> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return page;
        }

        List<Long> cdIds = records.stream().map(ProductionOrderDetail::getContractDetailId).collect(Collectors.toList());


        //获取产品信息
        List<Long> pIds = records.stream().map(ProductionOrderDetail::getProductId).collect(Collectors.toList());
        List<ProductInfo> productInfoList = productInfoService.list(q -> q.in(ProductInfo::getId, pIds));
        Map<Long, ProductInfo> productMap = productInfoList.stream().collect(Collectors.toMap(ProductInfo::getId, Function.identity()));
        //获取原材料信息
        List<ContractProductBom> rawMaterialBom = contractProductBomService.list(q -> q
                .in(ContractProductBom::getContractProductId, cdIds)
                .eq(ContractProductBom::getType, 1)
        );
        List<ContractProductBomVo> contractProductBomVoList = BeanUtil.copyToList(rawMaterialBom, ContractProductBomVo.class);
        productInfoService.attributeAssign(contractProductBomVoList, ContractProductBomVo::getMaterialId, (item, rawMaterial) -> {
            item.setProductCode(rawMaterial.getCustomCode());
            item.setProductName(rawMaterial.getName());
            item.setProductLength(rawMaterial.getLength());
            item.setProductWidth(rawMaterial.getWidth());
            item.setProductHeight(rawMaterial.getHeight());
            item.setProductColor(rawMaterial.getColor());
        });
        Map<Long, ContractProductBomVo> rawMaterialMap = contractProductBomVoList.stream().collect(Collectors.toMap(ContractProductBomVo::getContractProductId, Function.identity()));

        //获取生产进度列表
        List<Long> tIds = records.stream().map(ProductionOrderDetail::getId).collect(Collectors.toList());
        List<ProductionTaskProgressVo> productionTaskProgressList = productionTaskProgressMapper.getList(IWrapper.<ProductionTaskProgress>getWrapper()
                .in("ptp.task_id", tIds)
        );
        Map<Long, List<ProductionTaskProgressVo>> productionTaskProgressMap = productionTaskProgressList
                .stream().collect(Collectors.groupingBy(ProductionTaskProgress::getTaskId));

        //获取生产公司信息
        List<Long> companyIds = records.stream().map(ProductionOrderDetail::getCompanyId).collect(Collectors.toList());
        Map<Long, String> companyNameMap = DeptUstil.getDeptNameMap(companyIds);


        for (ProductionOrderDetailVo record : records) {
            //赋值产品信息
            ProductInfo product = productMap.get(record.getProductId());
            if (ObjectUtil.isNotEmpty(product)) {
                record.setProductCode(product.getCustomCode());
                record.setProductName(product.getName());
                record.setProductUnit(product.getUnit());
                record.setProductSpec(product.getSpec());
                record.setProductLength(product.getLength());
                record.setProductWidth(product.getWidth());
                record.setProductHeight(product.getHeight());
                record.setProductColor(product.getColor());

            }

            //赋值原材料信息
            ContractProductBomVo rawMaterial = rawMaterialMap.get(record.getContractDetailId());
            if (ObjectUtil.isNotEmpty(rawMaterial)) {
                record.setRawMaterialCode(rawMaterial.getProductCode());
                record.setRawMaterialName(rawMaterial.getProductName());
            }

            //赋值生产用时
            record.setUsageTime(0L);
            Date produceTime = record.getProduceTime();
            Date finishTime = record.getFinishTime();
            if (ObjectUtil.isNotEmpty(produceTime) && ObjectUtil.isNotEmpty(finishTime)) {
                long usageTime = finishTime.getTime() - produceTime.getTime();
                record.setUsageTime(usageTime / 1000 / 60 / 60);
            }

            //赋值生产进度列表
            record.setProductionTaskProgressList(productionTaskProgressMap.get(record.getId()));

            //赋值生产公司名称
            record.setCompanyName(companyNameMap.get(record.getCompanyId()));
        }

        return page;
    }

    @Override
    public ProductionOrderDetailVo detail(ProductionTaskDetailDto dto) {
        ProductionOrderDetailVo detail = BeanUtil.copyProperties(getById(dto.getId()), ProductionOrderDetailVo.class);
        Assert.notEmpty(detail, "查询不到任务明细信息！");

        return detailByIds(Arrays.asList(detail.getId())).get(0);
    }

    @Override
    public List<ProductionOrderDetailVo> detailByIds(List<Long> taskIds) {
        Assert.notEmpty(taskIds, "任务id列表不能为空");

        List<ProductionOrderDetail> productionOrderDetailList = this.list(q -> q.in(ProductionOrderDetail::getId, taskIds));
        List<ProductionOrderDetailVo> voList = BeanUtil.copyToList(productionOrderDetailList, ProductionOrderDetailVo.class);

        //赋值订单信息
        produceOrderService.attributeAssign(voList, ProductionOrderDetailVo::getProduceOrderId, (detail, order) -> {
            detail.setOrderCode(order.getCode());
            detail.setDeliveryPeriod(order.getDeliveryPeriod());
        });

        //赋值产品信息
        productInfoService.attributeAssign(voList, ProductionOrderDetailVo::getProductId, (detail, product) -> {
            detail.setProductCode(product.getCustomCode());
            detail.setProductName(product.getName());
            detail.setProductUnit(product.getUnit());
            detail.setProductSpec(product.getSpec());
            detail.setProductLength(product.getLength());
            detail.setProductWidth(product.getWidth());
            detail.setProductHeight(product.getHeight());
            detail.setProductColor(product.getColor());
        });
        //赋值产品备注
        contractProductService.attributeAssign(voList, ProductionOrderDetailVo::getContractDetailId, (detail, product) -> {
            detail.setProductRemark(product.getRemark());
        });

        //获取bom信息
        List<Long> cpIds = voList.stream().map(ProductionOrderDetailVo::getContractDetailId).collect(Collectors.toList());
        List<ContractProductBom> cpBomList = contractProductBomService.list(q -> q.in(ContractProductBom::getContractProductId, cpIds));
        List<ContractProductBomVo> cpBomVoList = BeanUtil.copyToList(cpBomList, ContractProductBomVo.class);
        productInfoService.attributeAssign(cpBomVoList, ContractProductBomVo::getMaterialId, (item, product1) -> {
            item.setProductCode(product1.getCustomCode());
            item.setProductName(product1.getName());

            item.setProductLength(product1.getLength());
            item.setProductWidth(product1.getWidth());
            item.setProductHeight(product1.getHeight());
            item.setProductColor(product1.getColor());
        });
        Map<Long, List<ContractProductBomVo>> bomMap = cpBomVoList.stream().collect(Collectors.groupingBy(ContractProductBom::getContractProductId));
        //获取原材料
        Map<Long, ContractProductBomVo> rawBomMap = cpBomVoList.stream()
                .filter(item -> Objects.equals(item.getType(), 1))
                .collect(Collectors.toMap(ContractProductBom::getContractProductId, Function.identity()));
        //其他BOM
        Map<Long, List<ContractProductBomVo>> otherBomMap = cpBomVoList.stream()
                .filter(item -> !Objects.equals(item.getType(), 1))
                .collect(Collectors.groupingBy(ContractProductBom::getContractProductId));

        //获取生产进度列表
        List<ProductionTaskProgressVo> productionTaskProgressList = productionTaskProgressMapper.getList(IWrapper.<ProductionTaskProgress>getWrapper()
                .in("ptp.task_id", taskIds)
        );
        Map<Long, List<ProductionTaskProgressVo>> ptpMap = productionTaskProgressList.stream().collect(Collectors.groupingBy(ProductionTaskProgress::getTaskId));

        for (ProductionOrderDetailVo detail : voList) {
            //赋值原材料信息
            ContractProductBomVo rawMaterialBom = rawBomMap.get(detail.getContractDetailId());
            if (ObjectUtil.isNotEmpty(rawMaterialBom)) {
                detail.setRawMaterialCode(rawMaterialBom.getProductCode());
                detail.setRawMaterialName(rawMaterialBom.getProductName());
                detail.setRawMaterialLength(rawMaterialBom.getProductLength());
                detail.setRawMaterialWidth(rawMaterialBom.getProductWidth());
                detail.setRawMaterialHeight(rawMaterialBom.getProductHeight());
                detail.setProductColor(rawMaterialBom.getProductColor());
            }
            //赋值BOM信息
            detail.setContractProductBomList(otherBomMap.get(detail.getContractDetailId()));

            //赋值生产进度列表
            detail.setProductionTaskProgressList(ptpMap.get(detail.getId()));
        }

        return voList;
    }

    @Override
    public void editRemark(ProductionOrderDetailDto dto) {
        Assert.notEmpty(dto.getId(), "生产任务id不能为空！");

        this.update(q -> q
                .eq(ProductionOrderDetail::getId, dto.getId())
                .set(ProductionOrderDetail::getRemark, dto.getRemark())
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
    }

}
