package com.cf.imes.module.executor.api.plan;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.module.executor.api.plan.vo.OrderGroupRespVO;
import com.cf.imes.module.executor.controller.admin.orderParts.vo.OrderPartsRemark;
import com.cf.imes.module.executor.controller.admin.plate.vo.PlateRespVO;
import com.cf.imes.module.executor.dal.dataobject.goods.GoodsDO;
import com.cf.imes.module.executor.dal.dataobject.goods.OptimizeBoardModelDO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.orderBody.OrderBodyDO;
import com.cf.imes.module.executor.dal.dataobject.orderItem.OrderItemDO;
import com.cf.imes.module.executor.dal.dataobject.orderParts.OrderPartsDO;
import com.cf.imes.module.executor.dal.dataobject.ordermodel.OrderModelDO;
import com.cf.imes.module.executor.dal.dataobject.plan.PlanDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO;
import com.cf.imes.module.executor.dal.dataobject.remainplaten.RemainPlateDO;
import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper;
import com.cf.imes.module.executor.dal.mysql.order.OrderMapper;
import com.cf.imes.module.executor.dal.mysql.orderBody.OrderBodyMapper;
import com.cf.imes.module.executor.dal.mysql.orderGroup.OrderGroupMapper;
import com.cf.imes.module.executor.dal.mysql.orderItem.OrderItemMapper;
import com.cf.imes.module.executor.dal.mysql.orderParts.OrderPartsMapper;
import com.cf.imes.module.executor.dal.mysql.plan.PlanMapper;
import com.cf.imes.module.executor.dal.mysql.plate.PlateMapper;
import com.cf.imes.module.executor.dal.mysql.remainplaten.RemainPlateMapper;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;

import jakarta.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import static com.cf.imes.framework.common.util.json.JsonUtils.toJsonString;
import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId;
import static com.cf.imes.module.executor.enums.EsIndexEnum.*;

@RestController // 提供 RESTful API 接口，给 Feign 调用
@Validated
@Slf4j
public class OrderPlanApiImpl implements OrderPlanApi{


    @Resource
    private PlanMapper planMapper;


    @Resource
    private GoodsMapper goodsMapper;


    @Resource
    private OrderMapper orderMapper;


    @Resource
    private RemainPlateMapper remainPlateMapper;


    @Resource
    private PlateMapper plateMapper;


    @Resource
    private OrderItemMapper orderItemMapper;


    @Resource
    private OrderBodyMapper orderBodyMapper;

    @Resource
    private OrderGroupMapper orderGroupMapper;

    @Resource
    private OrderPartsMapper orderPartsMapper;


    public static final String SEPARATE = "select";


    @Override
    public CommonResult<Boolean> getOrderPlan(Long machineId) {

        List<PlanDO> planDOS = planMapper.selectByMachineId(machineId, getUserOrganId());

        if(!planDOS.isEmpty()){

           return CommonResult.success(true);
        }

        return CommonResult.success(false);

    }


    @Override
    public CommonResult<Boolean> getOrder(Long orderId) {
        Long organId = getUserOrganId();

        List<PlateDO> plateDOS = plateMapper.selectNoCutPlateByPlateId(Collections.singletonList(orderId), organId);

        if (CollUtil.isNotEmpty(plateDOS)) {
            return CommonResult.success(false);
        }

        List<PlateDO> orderPlanPlateList = plateMapper.selectList(new LambdaQueryWrapper<PlateDO>()
                .eq(PlateDO::getOrderId, orderId)
                .eq(PlateDO::getOrganId, orderId)
                .ne(PlateDO::getPlanId, 0L)
                .select(PlateDO::getPlanId));

        if (CollUtil.isNotEmpty(orderPlanPlateList)) {

            List<Long> planIds = orderPlanPlateList.stream().map(PlateDO::getPlanId).distinct().toList();

            List<Long> planDOS = planMapper.selectPlanList(planIds, organId);

            if (CollUtil.isEmpty(planDOS)) {
                return CommonResult.success(true);
            }

        }

        return CommonResult.success(true);
    }




    @Override
    public CommonResult<Boolean> getOrderProcessScheme(Long processId) {

        List<PlanDO> planDOS = planMapper.selectProcessScheme(processId, getUserOrganId());

        return CommonResult.success(CollUtil.isNotEmpty(planDOS));
    }



    /*
     * 机台数据源数据查询
     *
     * */

    @Override
    public String apiDataGetPlan(Long planId,String filed) {

        PlanDO planDOS = planMapper.selectById(planId);

        List<Long> orderIds = JSON.parseArray(planDOS.getOrderNos()).toJavaList(Long.class);


        return toJsonString(orderMapper.selectOrderDataSource(conversion(filed),orderIds,getUserOrganId()));
    }



    @Override
    public String getGoods(Long planId,String filed)  {


        List<OptimizeBoardModelDO> optimizeBoardModelDOS = buildBoardByPlanId(planId, ORDER_OPTIMIZE_PLATE_MODEL.getIndex(), 10);



        JsonNode jsonNode = JsonUtils.parseTree(JsonUtils.toJsonString(optimizeBoardModelDOS));


        filed = filed.replace("place_block_number","");


        String filed2 = "place_block_number".equals(filed) ? ",{placeBlockNumber:"+jsonNode.get("placeBlockNumber").asLong()+"}]" : "";


        List<GoodsDO> goodsDO = goodsMapper.selectPlanGoodsDataSource(conversion(filed),planId,getUserOrganId());



        return "".equals(filed2) ? toJsonString(goodsDO) : toJsonString(goodsDO).replace("]", "") + filed2;

    }




    @Override
    public List<String> apiGetOrders(Long planId,Boolean isSale) {

        PlanDO planDOS = planMapper.selectById(planId);

        List<Long> orderIds = JSON.parseArray(planDOS.getOrderNos()).toJavaList(Long.class);


        return isSale ? orderMapper.selectBatchIds(orderIds).stream().map(OrderDO::getSalesman).distinct().toList()
                : orderMapper.selectBatchIds(orderIds).stream().map(OrderDO::getCreator).distinct().toList();


    }



    @Override
    public String getPlan(Long planId,String filed) {

        List<PlanDO> planDOS = planMapper.selectPlanDataSource(conversion(filed),planId,getUserOrganId());

        return toJsonString(planDOS);



    }

    @Override
    public String apiGetEsPlan(Long planId, List<String> fields) {


        List<String> esData = new ArrayList<>();


        List<OptimizeBoardModelDO> optimizeBoardModelDOS = buildBoardByPlanId(planId, ORDER_OPTIMIZE_PLATE_MODEL.getIndex(), 99);

        for (OptimizeBoardModelDO optimizeBoardModelDO : optimizeBoardModelDOS) {
            List<String> filedData = new ArrayList<>() ;

            JsonNode jsonNode = JsonUtils.parseTree(JsonUtils.toJsonString(optimizeBoardModelDO));

            for (String field : fields) {
                filedData.add(field+":"+ (jsonNode.get(field) == null ?"" : jsonNode.get(field).asText()));
            }

            esData.add(filedData.toString());

        }


        return esData.toString();


    }

    @Override
    public String apiGetPlanRemainPlate(Long planId, String field) {

        List<RemainPlateDO> remainPlateDOS = remainPlateMapper.selectPlanRemainDataSource(conversion(field),planId,getUserOrganId());


        return toJsonString(remainPlateDOS);


    }


    @Override
    public String apiGetPlanPlate(Long planId, String field) {

        List<GoodsDO> goodsDOS = goodsMapper.selectPlanGoods(planId, getUserOrganId());

        List<Long> goodsIds = goodsDOS.stream().map(GoodsDO::getId).distinct().toList();

        List<Long> orderIds = goodsDOS.stream().map(GoodsDO::getOrderId).distinct().toList();


        field = field
                .replace("sculpt_num", "sum(front_model_count+back_model_count) as sculptNum" + "")
                .replace("hole_num", "sum(unregular_point_count+front_hole_count+back_hole_count+side_hole_count) as holeNum" + "");


        String field2 = "sculpt_num".equals(field) || "hole_num".equals(field)  ? "group by  " + conversion(field)
                .replace("sum(front_model_count+back_model_count) as sculptNum", "")
                .replace("sum(unregular_point_count+front_hole_count+back_hole_count+side_hole_count) as holeNum", "") : "";


        field2 = field2.replaceFirst(",\\s*$", "");


        List<PlateRespVO> plateDOS = plateMapper.selectPlanPlateListDataSource(conversion(field),field2,goodsIds,orderIds,getUserOrganId());


        return toJsonString(plateDOS);

    }



    @Override
    public String apiGetEsPlate(Long planId, List<String> fields) {

        List<String> esData = new ArrayList<>();

        List<Long> plateIds = getPlateIds(planId);


        List<OrderModelDO> orderModelDOS = buildBoardByPlateIds(plateIds, ORDER_PLATE_MODEL.getIndex(), plateIds.size());


        for (OrderModelDO orderModelDO : orderModelDOS) {
            List<String> filedData = new ArrayList<>() ;

            JsonNode jsonNode = JsonUtils.parseTree(JsonUtils.toJsonString(orderModelDO));

            for (String field : fields) {

                BigDecimal splitLength = BigDecimal.valueOf(jsonNode.get("splitLength").asDouble());
                BigDecimal splitWidth = BigDecimal.valueOf(jsonNode.get("splitWidth").asDouble());

                filedData.add( "splitArea".equals(field)? "splitArea:"+ splitLength.multiply(splitWidth) : field+":"+jsonNode.get(field).asText());

            }


            esData.add(filedData.toString());

        }


        return esData.toString();

    }




    @Override
    public String apiGetPlanBodyOrRoom(Long planId, String field) {


        List<Long> bodyIds = goodsMapper.selectPlanBodyIds(planId, getUserOrganId());

        List<OrderBodyDO> orderBodyDOS = orderBodyMapper.selectPlanBodyRoomDataSource(conversion(field), bodyIds, getUserOrganId());


        return toJsonString(orderBodyDOS);

    }




    @Override
    public String apiGetPlanGroup(Long planId, String field) {


        List<Long> groupIds = goodsMapper.selectPlanGroupListDataSource(planId, getUserOrganId());

        if(groupIds.isEmpty()){
            return null;
        }

        field = field.replace("group_num", "count(id) as groupNum" + "");


        String field2 = ("group by  " + conversion(field).replace("count(id) as groupNum", "")).replaceFirst(",\\s*$", "");


        List<OrderGroupRespVO> orderGroupDOS = orderGroupMapper.selectPlanGroupDataSource(conversion(field),field2, groupIds, getUserOrganId());


        return toJsonString(orderGroupDOS);

    }





    @Override
    public String apiGetPlanParts(Long planId, String field) {

        List<Long> orderIds = goodsMapper.selectPlanGoods(planId, getUserOrganId()).stream().map(GoodsDO::getOrderId).distinct().toList();


        List<Long> partIds = orderPartsMapper.selectPartIds(orderIds, getUserOrganId()).stream().map(OrderPartsDO::getId).toList();


        String filed2 = "parts_num" .equals(field) ?
                ",{partsNum:"+orderItemMapper.selectPartsList(partIds,orderIds, getUserOrganId()).stream().mapToDouble(OrderItemDO::getNum).sum()+"}]" : "";


        List<OrderPartsDO> orderPartsDOS = orderPartsMapper.selectPlanPartsDataSource(conversion(field), partIds, getUserOrganId());


        return "".equals(filed2) ? toJsonString(orderPartsDOS) : toJsonString(orderPartsDOS).replace("]", "") + filed2;



    }





    @Override
    public String apiGetEsParts(Long planId, List<String> fields) {

        List<Long> orderIds = goodsMapper.selectPlanGoods(planId, getUserOrganId()).stream().map(GoodsDO::getOrderId).distinct().toList();

        int partNum = orderPartsMapper.selectPartList(orderIds, getUserOrganId()).size();

        List<String> esData = new ArrayList<>();

        List<OrderPartsRemark> orderPartsRemarks = buildOrderPartsByOrderId(orderIds, ORDER_PARTS_REMARK_MODEL.getIndex(), partNum);


        for (OrderPartsRemark orderPartsRemark : orderPartsRemarks) {

            List<String> filedData = new ArrayList<>();

            JsonNode jsonNode = JsonUtils.parseTree(JsonUtils.toJsonString(orderPartsRemark));

            for (String field : fields) {
                filedData.add(field+":" + (jsonNode.get(field) == null ? "" : jsonNode.get(field).asText()));
            }

            esData.add(filedData.toString());

        }


        return esData.toString();


    }


    // 字符串处理
    private String conversion(String filed) {

        // 去除字段中的 【 】
        return filed.replaceAll("\\[|\\]", "");

        // 使用正则表达式在单词后插入字符串
//        return sql.replaceAll(SEPARATE + "(\\b)", SEPARATE + " " + toInsert);

    }




    // 根据排单ID获取对应的板材ID
    private List<Long> getPlateIds(Long planId) {

        return goodsMapper.selectPlanPlateList(planId, getUserOrganId());

    }


    private List<OrderPartsRemark> buildOrderPartsByOrderId(List<Long> orderIds, String index, Integer size) {
        return new ArrayList<>();
    }




    private List<OptimizeBoardModelDO> buildBoardByPlanId(Long planId, String index, Integer size) {
        return new ArrayList<>();
    }




    private List<OrderModelDO> buildBoardByPlateIds(Collection<Long> plateIds, String index, Integer size) {
        return new ArrayList<>();
    }


    public static String toCamelCase(String fieldName) {
        if (fieldName == null || fieldName.isEmpty()) {
            return fieldName;
        }

        StringBuilder camelCase = new StringBuilder();
        boolean nextIsUpperCase = false;

        for (char c : fieldName.toCharArray()) {
            if (c == '_' || c == '-') {
                nextIsUpperCase = true;
            } else {
                if (nextIsUpperCase) {
                    camelCase.append(Character.toUpperCase(c));
                    nextIsUpperCase = false;
                } else {
                    camelCase.append(c);
                }
            }
        }

        return camelCase.toString();
    }



}
