package com.cf.imes.module.executor.util.fileConversion.admin.files.excel;

import com.cf.imes.framework.mybatis.core.generator.SnowFlakeGenerator;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.module.executor.dal.dataobject.goods.GoodsDO;
import com.cf.imes.module.executor.dal.dataobject.orderBody.OrderBodyDO;
import com.cf.imes.module.executor.dal.dataobject.orderGroup.OrderGroupDO;
import com.cf.imes.module.executor.dal.dataobject.orderItem.OrderItemDO;
import com.cf.imes.module.executor.dal.dataobject.orderModuleExtra.OrderModuleExtraDO;
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.plate.PlateDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateGoodDO;
import com.cf.imes.module.executor.dal.dataobject.rawgoods.RawGoodsDO;
import com.cf.imes.module.executor.enums.OrderItemTypeEnum;
import com.cf.imes.module.executor.util.fileConversion.admin.SnowflakeIdWorker3rd;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 实现数据格式转换
 * 使用自带id
 */
@Slf4j
@Component
public class ExcelTypeRealize {

    @Resource
    private SnowFlakeGenerator snowFlakeGenerator;

    @Resource
    SnowflakeIdWorker3rd idWorker;

    // 数据转换 + 错误验证
    public Map<String, List<?>> changeDate(List<?> list, Long orderId) {
        if (list.isEmpty()){
//            throw exception(FILE_UPLOAD_ERR);
            return null;
        }

        List<OrderPlateImportExcelVO> excelVOS = (List<OrderPlateImportExcelVO>) list;
        Map<String, List<?>> map = new HashMap<>();

        Long organId = OrganContextHolder.getOrganId();
        ArrayList<RawGoodsDO> rawGoodsDOS = new ArrayList<>();
        ArrayList<GoodsDO> goodsDOS = new ArrayList<>();
        ArrayList<PlateGoodDO> plateGoodDOS = new ArrayList<>();
        ArrayList<OrderBodyDO> orderBodyDOS = new ArrayList<>();
        ArrayList<OrderGroupDO> orderGroupDOS = new ArrayList<>();
        ArrayList<PlateDO> plateDOS = new ArrayList<>();
        ArrayList<OrderPartsDO> orderPartsDOS = new ArrayList<>();
        ArrayList<OrderItemDO> orderItemDOS = new ArrayList<>();
        ArrayList<OrderModuleExtraDO> orderModuleExtraDOS = new ArrayList<>();
        ArrayList<OrderModelDO> orderModelDOS = new ArrayList<>();

        HashMap<String, List<OrderPlateImportExcelVO>> checkMap = classifyGoods(excelVOS);

        Map<String, List<OrderPlateImportExcelVO>> goodsIdMap = checkMap.get("plate").stream().collect(
                Collectors.groupingBy(
                        excelVO -> excelVO.getGoodsId() != null ? excelVO.getGoodsId() : " ",
                        Collectors.toList()
                ));
        goodsIdMap.forEach((key, value) -> {
            if (value.get(0).getGoodsId() == null) { // 没有商品编号的
//                将相同条件的元素归为一个集合
                Map<List<Object>, List<OrderPlateImportExcelVO>> goodsMap = value.stream()
                        .collect(Collectors.groupingBy(
                                p -> Arrays.asList(p.getGoodsName(),
                                        p.getGoodsName(),
                                        p.getThickness(),
                                        p.getMaterial(),
                                        p.getColor(),
                                        p.getSpec(),
                                        p.getTexture(),
                                        p.getModel(),
                                        p.getBrand()),
                                Collectors.toList()
                        ));

                goodsMap.forEach((goodKey, goodValue) -> {
//                    板材信息合集，添加生产单id，添加生产单板材设计端商品编码，板材信息写入order_raw_goods
//                    规格分解
                    List<Double> specList = spec(goodValue.get(0).getSpec());
                    RawGoodsDO rawGoodsDO = setRawGoodsDO(goodValue.get(0)).setId((Long) snowFlakeGenerator.nextId(null)).setOrderId(orderId);
                    rawGoodsDOS.add(rawGoodsDO);
                    Long goodId = (Long) snowFlakeGenerator.nextId(null);
                    GoodsDO plateDO = setGoodsDO(goodValue.get(0)).setId(goodId).setOrderId(orderId)
                            .setRawGoodsId(String.valueOf(rawGoodsDO.getId()))
                            .setHeight(BigDecimal.valueOf(specList.get(0))).setWidth(BigDecimal.valueOf(specList.get(1))); // 在good_id为空的时候，首先赋值为空值
                    goodsDOS.add(plateDO);
//                  赋值给板件未对应前order_raw_goods的id
                    for (OrderPlateImportExcelVO reqVO : goodValue) {
                        reqVO.setGoodId(goodId);
                    }
                });
            } else { // 商品编码有的
                List<Double> specList = spec(value.get(0).getSpec());
//              板材信息合集，添加生产单id，添加生产单板材设计端商品编码，板材信息写入order_raw_goods
                RawGoodsDO rawGoodsDO = setRawGoodsDO(value.get(0)).setId((Long) snowFlakeGenerator.nextId(null)).setOrderId(orderId);
                rawGoodsDOS.add(rawGoodsDO);
                Long goodId = (Long) snowFlakeGenerator.nextId(null);
                GoodsDO plateDO = setGoodsDO(value.get(0)).setId(goodId).setOrderId(orderId)
                        .setRawGoodsId(String.valueOf(rawGoodsDO.getId())).setGoodsId(String.valueOf(rawGoodsDO.getRawGoodsId()))
                        .setHeight(BigDecimal.valueOf(specList.get(0))).setWidth(BigDecimal.valueOf(specList.get(1)));
                goodsDOS.add(plateDO);

//              赋值给板件未对应前order_raw_goods的id
                for (OrderPlateImportExcelVO reqVO : value) {
                    reqVO.setGoodId(goodId);
                }
            }
        });


        // 房间名称为条件进行分组
        Map<String, List<OrderPlateImportExcelVO>> roomCollect = excelVOS.stream().collect(
                Collectors.groupingBy(
                        excelVO -> excelVO.getRoomsName() != null ? excelVO.getRoomsName() : " ",
                        Collectors.toList()
                ));
        System.out.println("roomCollect " + roomCollect);

        roomCollect.forEach((roomName, listRoom) -> {
            Long roomId = (Long) snowFlakeGenerator.nextId(null);
            // 柜体名称为条件进行分组
            Map<String, List<OrderPlateImportExcelVO>> bodyCollect = listRoom.stream()
                    .collect(Collectors.groupingBy(
                            excelVO -> excelVO.getCabinetsName() != null ? excelVO.getCabinetsName() : " ",
                            Collectors.toList()
                    ));

            bodyCollect.forEach((bodyName, listBody) -> {
                Long bodyId = (Long) snowFlakeGenerator.nextId(null);
                final Double[] plateCountByCabinetName = {0.0};
                OrderBodyDO orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId)
                        .roomId(roomId).roomName(roomName).name(bodyName).width(0.0).height(0.0)
                        .depth(0.0).multiNum(0).plateNum(0).unregularNum(0).filename("无").remark("无").build(); //没有获取柜体的长宽高


                // 加工组类型为条件进行分组
                Map<String, List<OrderPlateImportExcelVO>> synthesisCollect = listBody.stream()
                        .collect(Collectors.groupingBy(
                                excelVO -> excelVO.getSynthesis() != null ? excelVO.getSynthesis() : " ",
                                Collectors.toList()
                        ));
                Long groupTypeId = (Long) snowFlakeGenerator.nextId(null);

                synthesisCollect.forEach((synthesis, listSynthesis) -> {
                    // 加工组名称为条件进行分组
                    Map<String, List<OrderPlateImportExcelVO>> combinationNameCollect = listSynthesis.stream()
                            .collect(Collectors.groupingBy(
                                    excelVO -> excelVO.getCombinationName() != null ? excelVO.getCombinationName() : " ",
                                    Collectors.toList()
                            ));
                    combinationNameCollect.forEach((combinationName, listCombinationName) -> {
                        Long groupId = (Long) snowFlakeGenerator.nextId(null);
//                            板数量
                        final Double[] plateCountByCombination = {0.0};
                        OrderGroupDO orderGroupDO = OrderGroupDO.builder().id(groupId).orderId(orderId).orderId(organId).bodyId(bodyId)
                                .groupTypeId(groupTypeId).groupTypeName(synthesis).name(combinationName).width(0.0).height(0.0)
                                .depth(0.0).multiNum(0).plateNum(0).unregularNum(0).filename("无").remark("无").build();

                        listCombinationName.forEach(combination -> {

                            if (combination.getGoodType().equals("板材")) {
                                //板材
                                plateCountByCombination[0] = plateCountByCombination[0] + Double.parseDouble(combination.getGoodsNumber());
                                for (int i = 0; i < Integer.parseInt(combination.getGoodsNumber()); i++) {
                                    long plateNo = idWorker.nextId();
                                    long obtainingTime = idWorker.obtainingTime();

                                    Long plateId = (Long) snowFlakeGenerator.nextId(null);
                                    PlateDO plateDO = PlateDO.builder()
                                            .id(plateId).orderId(orderId).name(combination.getName()).plateNo(combination.getPlateNo())
                                            .goodsId(combination.getGoodId()).width(BigDecimal.valueOf(Double.parseDouble(combination.getWidth())))
                                            .plateNo(((obtainingTime)+ Long.toString(plateNo).substring(2)))
                                            .height(BigDecimal.valueOf(Double.parseDouble(combination.getHeight())))
                                            .thickness(BigDecimal.valueOf(Double.parseDouble(combination.getThickness())))
                                            .splitWidth(BigDecimal.valueOf(Double.parseDouble(combination.getSplitWidth())))
                                            .splitHeight(BigDecimal.valueOf(Double.parseDouble(combination.getSplitHeight())))
                                            .splitThickness(BigDecimal.valueOf(Double.parseDouble(combination.getThickness())))
                                            .sealLeft(BigDecimal.valueOf(Double.parseDouble(combination.getSealLeft())))
                                            .sealRight(BigDecimal.valueOf(Double.parseDouble(combination.getSealRight())))
                                            .sealUp(BigDecimal.valueOf(Double.parseDouble(combination.getSealUp())))
                                            .sealDown(BigDecimal.valueOf(Double.parseDouble(combination.getSealDown())))
                                            .holeFace(Integer.valueOf(combination.getTypographicFace()))
                                            .texture(Integer.valueOf(combination.getTexture()))
                                            .openDoorType(Integer.valueOf(combination.getOpenDoorType()))
                                            .isSpecialShaped(false)
                                            .isSculpt(false)
                                            .remark(combination.remarkJSON())
                                            .build();
                                    plateDOS.add(plateDO);

                                    OrderItemDO orderItemDO = OrderItemDO.builder().orderId(orderId).type(OrderItemTypeEnum.PLATE_ITEM.getStatus())
                                            .roomId(roomId).bodyId(bodyId).plateId(plateId)
                                            .num(1.0).groupId(groupId).build();
                                    orderItemDOS.add(orderItemDO);
                                    orderModelDOS.add(OrderModelDO.builder().orderId(orderId).plateId(plateId)
                                            .typographicFace(Integer.valueOf(combination.getTypographicFace())).build());
                                }
                                plateCountByCabinetName[0] = plateCountByCabinetName[0] + plateCountByCombination[0];

                            } else {
                                //配件
                                Long partsId = (Long) snowFlakeGenerator.nextId(null);
                                OrderPartsDO orderPartsDO = OrderPartsDO.builder().id(partsId).orderId(orderId).goodsId(combination.getGoodsId())
                                        .name(combination.getGoodsName()).material(combination.getMaterial()).type(combination.getGoodType())
                                        .model(combination.getModel()).spec(combination.getSpec()).brand(combination.getBrand()).factory(combination.getFactory())
                                        .unit(combination.getUnit()).price(0.0).isComposite(false).remark(combination.remarkJSON()).isComposite(false).build();
                                orderPartsDOS.add(orderPartsDO);
                                OrderItemDO orderItemDO = OrderItemDO.builder().orderId(orderId).type(OrderItemTypeEnum.PARTS_ITEM.getStatus())
                                        .roomId(roomId).bodyId(bodyId).partsId(partsId).groupId(groupId)
                                        .num(Double.valueOf(combination.getGoodsNumber())).build();
                                orderItemDOS.add(orderItemDO);
                            }

                        });
                        orderGroupDO.setPlateNum(plateCountByCombination[0].intValue());
                        orderGroupDOS.add(orderGroupDO);
                    });
                });
                orderBodyDO.setPlateNum(Integer.valueOf(plateCountByCabinetName[0].intValue()));
                orderBodyDOS.add(orderBodyDO);
            });
        });

        map.put("rawGoodsDOS", rawGoodsDOS);
        map.put("goodsDOS", goodsDOS);
        map.put("plateGoodDOS", plateGoodDOS);
        map.put("orderBodyDOS", orderBodyDOS);
        map.put("orderGroupDOS", orderGroupDOS);
        map.put("plateDOS", plateDOS);
        map.put("orderPartsDOS", orderPartsDOS);
        map.put("orderItemDOS", orderItemDOS);
        map.put("orderModuleExtraDOS", orderModuleExtraDOS);
        map.put("orderModelDOS", orderModelDOS);
        return map;
    }

    // 板材库数据
    private PlateGoodDO setPlateGoodDO(OrderPlateImportExcelVO excelVO) {
        return PlateGoodDO.builder()
//                .id(plateGoodId)
                .goodsId("")
                .goodsName(excelVO.getGoodsName())
                .material(excelVO.getMaterial())
                .color(excelVO.getColor())
                .width(Double.valueOf(excelVO.getWidth()))
                .height(Double.valueOf(excelVO.getHeight()))
                .thickness(Double.valueOf(excelVO.getThickness()))
                .spec(excelVO.getSpec())
                .brand(excelVO.getBrand())
                .texture(excelVO.getTexture())
//                .organId(organId)
                .build();
    }

    // RawGoodsDO数据
    private RawGoodsDO setRawGoodsDO(OrderPlateImportExcelVO excelVO) {
        return RawGoodsDO.builder()
//                .id(rawGoodsId)
//                .orderId(orderId)
                .rawGoodsId(excelVO.getGoodsId())
                .goodsName(excelVO.getGoodsName())
                .material(excelVO.getMaterial())
                .color(excelVO.getColor())
                .thickness(Double.valueOf(excelVO.getThickness()))
                .spec(excelVO.getSpec())
                .brand(excelVO.getBrand())
                .texture(Integer.valueOf(excelVO.getTexture()))
                .build();
    }

    // GoodsDO数据
    private GoodsDO setGoodsDO(OrderPlateImportExcelVO excelVO) {
        return GoodsDO.builder()
//                .id(goodId)
//                .orderId(orderId)
//                .rawGoodsId(rawGoodsId)
//                .goodsId(plateGoodId)
                .goodsName(excelVO.getGoodsName())
                .material(excelVO.getMaterial())
                .color(excelVO.getColor())
                .width(BigDecimal.valueOf(Double.valueOf(excelVO.getWidth())))
                .height(BigDecimal.valueOf(Double.valueOf(excelVO.getHeight())))
                .thickness(BigDecimal.valueOf(Double.valueOf(excelVO.getThickness())))
                .spec(excelVO.getSpec())
                .brand(excelVO.getBrand())
                .build();
    }

    // spec分离数据
    public List<Double> spec(String spec) {
        List<Double> list = new ArrayList<>();

        String[] parts = spec.split("\\×");
        if (parts.length <= 1) {
            return null;
        }
        for (int i = 0; i < 3; i++) {
            Double num = 0.0;
            try {
                if (i < parts.length)
                    num = Double.parseDouble(parts[i]);
            } catch (NumberFormatException e) {
                // 转换失败，保持num为0
            }
            list.add(num);
        }
        return list;
    }

    //    对数据进行分类
    private HashMap<String, List<OrderPlateImportExcelVO>> classifyGoods(List<OrderPlateImportExcelVO> list) {
        HashMap<String, List<OrderPlateImportExcelVO>> map = new HashMap<>();
        List<OrderPlateImportExcelVO> plateLists = new ArrayList<>();
        List<OrderPlateImportExcelVO> partsLists = new ArrayList<>();
        for (OrderPlateImportExcelVO detail : list) {
            //判断是板材还是配件
            if (detail.getGoodType().equals("板材")) {
                plateLists.add(detail);
            } else {
                partsLists.add(detail);
            }
        }
        map.put("plate", plateLists);
        map.put("parts", partsLists);
        return map;
    }
}
