package com.jwipc.order.api.logic.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.google.common.collect.Maps;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.dto.ApiResult;
import com.jwipc.log.annotation.ApiOperateLog;
import com.jwipc.log.constant.ApiDirection;
import com.jwipc.log.constant.ThirdSysType;
import com.jwipc.order.api.dto.CreateBasicPlanDTO;
import com.jwipc.order.api.logic.CreateBasicPlanLogic;
import com.jwipc.order.constants.BasicPlanConst;
import com.jwipc.order.entity.BasicForcaseData;
import com.jwipc.order.entity.BasicForcaseDetail;
import com.jwipc.order.entity.BasicPlan;
import com.jwipc.order.service.IBasicForcaseDataService;
import com.jwipc.order.service.IBasicForcaseDetailService;
import com.jwipc.order.service.IBasicPlanService;
import com.jwipc.sys.client.FactoryClient;
import com.jwipc.sys.client.ProductClient;
import com.jwipc.sys.client.PurchaseGroupClient;
import com.jwipc.sys.client.dto.FactoryDTO;
import com.jwipc.sys.client.dto.ProductInfoDTO;
import com.jwipc.sys.client.dto.PurchaseGroupDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Author: swq
 * @Date: 2024/4/3 12:27
 */
@Service
@RequiredArgsConstructor
public class CreateBasicPlanLogicImpl implements CreateBasicPlanLogic {
    private final PurchaseGroupClient purchaseGroupClient;
    private final FactoryClient factoryClient;
    private final ProductClient productClient;
    private final IBasicPlanService basicPlanService;
    private final IBasicForcaseDetailService detailService;
    private final IBasicForcaseDataService dataService;


    @Transactional(rollbackFor = Exception.class)
    @ApiOperateLog(code = "createBasicPlan", name = "创建预测计划", direction = ApiDirection.OTHER_TO_SRM,
            thirdSysType = ThirdSysType.SAP)
    public ApiResult createBasicPlan(CreateBasicPlanDTO createBasicPlanDTO) {
        final List<CreateBasicPlanDTO.Item> itItem = createBasicPlanDTO.getIT_ITEM();
        if (CollUtil.isEmpty(itItem)) {
            return ApiResult.builder().message("标准预测计划为空！")
                    .code(RestCode.SAP_ERROR.getCode()).build();
        }

        //物料数据缓存 key=factory_code+material_code
        Map<String, ProductInfoDTO> productCache = Maps.newHashMap();
        //工厂数据缓存
        final List<FactoryDTO> all = factoryClient.getAll();
        final Map<String, FactoryDTO> factoryCache = all.stream()
                .collect(Collectors.toMap(FactoryDTO::getFactory, a -> a));
        final Set<String> factoryCodes = factoryCache.keySet();
        final LocalDate now = LocalDate.now();
        final long maxVersion = basicPlanService.findMaxVersion();
        final long nextVersion = maxVersion + 1;
       //先校验
        for (CreateBasicPlanDTO.Item basicPlanDTO : itItem) {
            //工厂校验
            final String werks = basicPlanDTO.getWERKS();
            if (!factoryCodes.contains(werks)) {
                return ApiResult.builder().message(StrUtil.format("{},工厂不存在!", werks))
                        .code(RestCode.SAP_ERROR.getCode()).build();
            }
            //物料校验
            final String matnr = basicPlanDTO.getMATNR();
            if (StrUtil.isNotEmpty(matnr)) {
                final ProductInfoDTO cacheVal = productCache.get(werks + matnr);
                if (Objects.isNull(cacheVal)) {
                    ProductInfoDTO productInfoDTO = productClient.getByMaterialCodeAndFactoryCode(matnr, werks);
                    if (Objects.isNull(productInfoDTO)) {
                        return ApiResult.builder().message(StrUtil.format("{},物料不存在!", matnr))
                                .code(RestCode.SAP_ERROR.getCode()).build();
                    }
                    productCache.put(werks + matnr, productInfoDTO);
                }
            }
            //采购组校验
            final String ekgrp = basicPlanDTO.getEKGRP();
            final PurchaseGroupDTO purchaseGroupDTO = purchaseGroupClient.getByCode(ekgrp);
            if (Objects.isNull(purchaseGroupDTO)) {
                return ApiResult.builder().message(StrUtil.format("{},采购组编码不存在!", ekgrp))
                        .code(RestCode.SAP_ERROR.getCode()).build();
            }

        }
            //插入标准计划表数据
        BasicPlan plan = new BasicPlan();
        plan.setVersion(nextVersion);
        plan.setCreateTime(LocalDateTime.now());
        plan.setCreateId(1 + StringPool.EMPTY);
        plan.setStatus(1);
        plan.setTitle("SAP推送");
        plan.setStartTime(now);
        plan.setEndTime(now.plusDays(60));
        basicPlanService.save(plan);

        for (CreateBasicPlanDTO.Item basicPlanDTO : itItem) {
            //工厂校验
            final String werks = basicPlanDTO.getWERKS();
            //物料校验
            final String matnr = basicPlanDTO.getMATNR();
            //采购组校验
            final String ekgrp = basicPlanDTO.getEKGRP();

            BasicForcaseDetail bfDetail = new BasicForcaseDetail();
            bfDetail.setPlanId(plan.getId());
            bfDetail.setFactoryCode(werks);
            bfDetail.setProductCode(matnr);
            bfDetail.setProductName(basicPlanDTO.getMAKTX());
            bfDetail.setProductLongName(basicPlanDTO.getZTDLINE());
            bfDetail.setPurchaseGroup(ekgrp);
            bfDetail.setVersion(nextVersion);
            bfDetail.setCreateTime(now);
            BigDecimal onOrderNum = basicPlanDTO.getMENGE() == null ? BigDecimal.ZERO : basicPlanDTO.getMENGE();//在途订单量
            bfDetail.setOnOrderNum(onOrderNum);
            detailService.save(bfDetail);

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            List<BasicForcaseData> forcaseDataList = new ArrayList<>();
            BasicForcaseData data1 = new BasicForcaseData();
            data1.setDetailId(bfDetail.getId());
            data1.setNum(basicPlanDTO.getMENGE1()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE1());
            data1.setVersion(nextVersion);
            data1.setDateTime(now.plusMonths(0).format(formatter));
            data1.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data1);

            BasicForcaseData data2 = new BasicForcaseData();
            data2.setDetailId(bfDetail.getId());
            data2.setNum(basicPlanDTO.getMENGE2()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE2());
            data2.setVersion(nextVersion);
            data2.setDateTime(now.plusMonths(1).format(formatter));
            data2.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data2);

            BasicForcaseData data3 = new BasicForcaseData();
            data3.setDetailId(bfDetail.getId());
            data3.setNum(basicPlanDTO.getMENGE3()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE3());
            data3.setVersion(nextVersion);
            data3.setDateTime(now.plusMonths(2).format(formatter));
            data3.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data3);

            BasicForcaseData data4 = new BasicForcaseData();
            data4.setDetailId(bfDetail.getId());
            data4.setNum(basicPlanDTO.getMENGE4()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE4());
            data4.setVersion(nextVersion);
            data4.setDateTime(now.plusMonths(3).format(formatter));
            data4.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data4);

            BasicForcaseData data5 = new BasicForcaseData();
            data5.setDetailId(bfDetail.getId());
            data5.setNum(basicPlanDTO.getMENGE5()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE5());
            data5.setVersion(nextVersion);
            data5.setDateTime(now.plusMonths(4).format(formatter));
            data5.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data5);

            BasicForcaseData data6 = new BasicForcaseData();
            data6.setDetailId(bfDetail.getId());
            data6.setNum(basicPlanDTO.getMENGE6()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE6());
            data6.setVersion(nextVersion);
            data6.setDateTime(now.plusMonths(5).format(formatter));
            data6.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data6);

            BasicForcaseData data7 = new BasicForcaseData();
            data7.setDetailId(bfDetail.getId());
            data7.setNum(basicPlanDTO.getMENGE7()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE7());
            data7.setVersion(nextVersion);
            data7.setDateTime(now.plusMonths(6).format(formatter));
            data7.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data7);

            BasicForcaseData data8 = new BasicForcaseData();
            data8.setDetailId(bfDetail.getId());
            data8.setNum(basicPlanDTO.getMENGE8()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE8());
            data8.setVersion(nextVersion);
            data8.setDateTime(now.plusMonths(7).format(formatter));
            data8.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data8);

            BasicForcaseData data9 = new BasicForcaseData();
            data9.setDetailId(bfDetail.getId());
            data9.setNum(basicPlanDTO.getMENGE9()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE9());
            data9.setVersion(nextVersion);
            data9.setDateTime(now.plusMonths(8).format(formatter));
            data9.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data9);

            BasicForcaseData data10 = new BasicForcaseData();
            data10.setDetailId(bfDetail.getId());
            data10.setNum(basicPlanDTO.getMENGE10()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE10());
            data10.setVersion(nextVersion);
            data10.setDateTime(now.plusMonths(9).format(formatter));
            data10.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data10);

            BasicForcaseData data11 = new BasicForcaseData();
            data11.setDetailId(bfDetail.getId());
            data11.setNum(basicPlanDTO.getMENGE11()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE11());
            data11.setVersion(nextVersion);
            data11.setDateTime(now.plusMonths(10).format(formatter));
            data11.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data11);

            BasicForcaseData data12 = new BasicForcaseData();
            data12.setDetailId(bfDetail.getId());
            data12.setNum(basicPlanDTO.getMENGE12()== null ? BigDecimal.ZERO: basicPlanDTO.getMENGE12());
            data12.setVersion(nextVersion);
            data12.setDateTime(now.plusMonths(11).format(formatter));
            data12.setDateType(BasicPlanConst.dateType.month);
            forcaseDataList.add(data12);
            for(BasicForcaseData data:forcaseDataList){
                BigDecimal num = data.getNum();
                //在途订单量>0
                if (onOrderNum.compareTo(BigDecimal.ZERO) > 0) {
                    //在途订单量>发布量时，订单未清数量=发布数量
                    if (onOrderNum.compareTo(num) > 0) {
                        data.setPoNum(num);
                    }
                    if (onOrderNum.compareTo(num) == 0) {
                        data.setPoNum(num);
                    }
                    if (onOrderNum.compareTo(num) < 0) {
                        data.setPoNum(onOrderNum);
                    }
                    onOrderNum = onOrderNum.subtract(num);
                }

            }

            if (CollUtil.isNotEmpty(forcaseDataList)) {
                dataService.saveBatch(forcaseDataList);
            }


        }
        return ApiResult.builder().code(RestCode.SAP_SUCCESS.getCode()).build();
    }
}
