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

import com.alibaba.excel.EasyExcel;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.nacos.common.utils.StringUtils;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.system.api.dict.DictDataApi;
import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO;
import com.cf.imes.module.system.enums.DictTypeConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Component
public class ExcelReadUtil {  // 文件读取

    private Boolean index = true;

    private int isErr;

    @Resource
    private DictDataApi dictDataApi;

    // 读excel
    public Map<String, Object> read(MultipartFile file) throws IOException {
        Map<String, Object> map = new HashMap<>();
        ExcelListener excelListener = new ExcelListener();

        // 读文件
        EasyExcel.read(file.getInputStream(), excelListener).headRowNumber(-1).sheet().doRead();

        Map<Object, Object> orderMap = new HashMap<>();// order
        List<Map<Integer, String>> dataLists = excelListener.getDataLists();// 读取的内容
        List<OrderPlateImportExcelVO> list = new ArrayList<>();// plate

        dataLists.forEach(
                item -> {
                    if (item.get(0).equals("###")) {
                        index = false;
                    }
                    if (index) {
                        orderMap.put(item.get(0), item.get(1));
                        orderMap.put(item.get(12), item.get(13));
                    } else {
                        if (!(item.get(0).equals("序号") || item.get(0).equals("###"))) {
                            list.add(changeValue(item));
                        }

                    }
                }
        );
        index = true;
        map.put("order", orderMap);
        if (orderMap.size() == 0)
            isErr = -1;
        if (list.size() == 0)
            isErr = -1;
        map.put("plate", list);
        return map;

    }

    // order 数据转换
    public OrderDO changeOrderDO(Map<Object, Object> orderMap) {
        String s = (String) orderMap.get("出货日期");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate orderDate = LocalDate.parse(s, formatter);

        OrderDO orderDO = OrderDO.builder()
                .organId(OrganContextHolder.getOrganId())
                .dataType(0)
                .customer((String) orderMap.get("客户"))
                .customOrderNo((String) orderMap.get("自定义单号"))
                .dealer((String) orderMap.get("经销商"))
                .dealerPhoneNumber((String) orderMap.get("经销商电话"))
                .address((String) orderMap.get("客户地址"))
                .phoneNumber((String) orderMap.get("客户电话"))
                .salesman((String) orderMap.get("业务员"))
                .deliveryDate(orderDate.atStartOfDay())
                .splitter((String) orderMap.get("拆单员"))
                .remark((String) orderMap.get("备注"))
                .build();
        return orderDO;
    }

    private LocalDateTime changeTime(String dateString) {

        // 使用 DateTimeFormatter 解析字符串为 LocalDateTime 对象
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        LocalDateTime dateTime = LocalDateTime.parse(dateString, formatter);

        // 打印解析后的 LocalDateTime 对象
        System.out.println("Parsed LocalDateTime: " + dateTime);
        return dateTime;
    }

    // 赋值单元格数据
    private OrderPlateImportExcelVO changeValue(Map<Integer, String> dataMap) {
        OrderPlateImportExcelVO vo = new OrderPlateImportExcelVO();

        for (Map.Entry<Integer, String> entry : dataMap.entrySet()) {
            Integer key = entry.getKey();
            String value = entry.getValue();

            switch (key) {
                case 0:
                    vo.setOrdinal(value);
                    break;
                case 1:// 类型
                    vo.setGoodType(value);
                    break;
                case 2:// 物料编码
                    vo.setGoodsId(value);
                    break;
                case 3:// 商品名称
                    vo.setGoodsName(value);
                    break;
                case 4:// 材质
                    vo.setMaterial(value);
                    break;
                case 5:// 颜色
                    vo.setColor(value);
                    break;
                case 6:// 厂家
                    vo.setFactory(value);
                    break;
                case 7:// 品牌
                    vo.setBrand(value);
                    break;
                case 8:// 型号
                    vo.setModel(value);
                    break;
                case 9:// 规格
                    vo.setSpec(value);
                    break;
                case 10:// 单位
                    vo.setUnit(value);
                    break;
                case 11:// 数量
                    vo.setGoodsNumber(value);
                    break;
                case 12:// 房间
                    vo.setRoomsName(value);
                    break;
                case 13:// 柜体
                    vo.setCabinetsName(value);
                    break;
                case 14:// 加工组类型

                    vo.setSynthesisTypeName(value);
                    break;
                case 15:// 加工组名称
                    vo.setCombinationName(value);
                    break;
                case 16://板名称
                    vo.setName(value);
                    break;
                case 17:// 自定义板编号
                    vo.setPlateNo(value);
                    break;
                case 18:// 成品长
                    vo.setHeight(value);
                    break;
                case 19:// 成品宽
                    vo.setWidth(value);
                    break;
                case 20:// 拆单长
                    vo.setSplitHeight(value);
                    break;
                case 21:// 拆单宽
                    vo.setSplitWidth(value);
                    break;
                case 22:// 厚
                    vo.setThickness(value);
                    break;
                case 23:// 左封边
                    vo.setSealLeft(value);
                    break;
                case 24:// 右封边
                    vo.setSealRight(value);
                    break;
                case 25:// 上封边
                    vo.setSealUp(value);
                    break;
                case 26:// 下封边
                    vo.setSealDown(value);
                    break;
                case 27:// 排版面
                    vo.setTypographicFace(value);
                    break;
                case 28:// 纹路
                    vo.setTexture(value);
                    break;
                case 29:// 开门方向
                    vo.setOpenDoorType(value);
                    break;
                case 30://备注1
                    vo.setRemark1(value);
                    break;
                case 31://备注2
                    vo.setRemark2(value);
                    break;
                case 32://备注3
                    vo.setRemark3(value);
                    break;
                case 33://备注4
                    vo.setRemark4(value);
                    break;
                case 34://备注5
                    vo.setRemark5(value);
                    break;
                case 35://备注6
                    vo.setRemark6(value);
                    break;
                case 36://备注7
                    vo.setRemark7(value);
                    break;
                case 37://备注8
                    vo.setRemark8(value);
                    break;
                case 38://备注9
                    vo.setRemark9(value);
                    break;
                case 39://备注10
                    vo.setRemark10(value);
                    break;
                default:
                    // 处理默认情况，可以选择忽略或者做其他处理
                    break;
            }
        }
        checkVO(vo);
        return vo;
    }

    // OrderPlateImportExcelVO 数据验证
    private Boolean checkVO(OrderPlateImportExcelVO vo) {
        List<String> errList = new ArrayList<>();
        Boolean flag = true;
        // 检查非空 类型、数量
        if (StringUtils.isEmpty(vo.getGoodType()) || StringUtils.isEmpty(vo.getGoodsNumber())) {
            errList.add("类型、数量不能为空");
            flag = false;
        }
        // 检查商品物料编码或是商品名称、规格、材质、颜色不可全为空
        if (StringUtils.isEmpty(vo.getGoodsId()) && (StringUtils.isEmpty(vo.getGoodsName()) || StringUtils.isEmpty(vo.getSpec())
                || StringUtils.isEmpty(vo.getMaterial()) || StringUtils.isEmpty(vo.getColor()) || StringUtils.isEmpty(vo.getUnit()))) {
            errList.add("商品物料编码或是商品名称、规格、材质、颜色、单位不可全为空");
            flag = false;
        }
        // 若商品类型为板材，需检查房间、柜体、板名称、成品长、成品宽、拆单长、拆单宽、厚、左封边、右封边、上封边、下封边、排版面、纹路、开门方向不能为空
        if (StringUtils.equals(vo.getGoodType(), "板材")) {
            if (StringUtils.isEmpty(vo.getRoomsName()) && StringUtils.isEmpty(vo.getCabinetsName()) && StringUtils.isEmpty(vo.getName())) {
                flag = false;
                errList.add("房间、柜体、板名称不能为空");
            }
            //成品长、成品宽、拆单长、拆单宽、厚、左封边、右封边、上封边、下封边 不能为空
            if (StringUtils.isEmpty(vo.getHeight()) && StringUtils.isEmpty(vo.getWidth()) && StringUtils.isEmpty(vo.getSplitHeight())
                    && StringUtils.isEmpty(vo.getSplitWidth()) && StringUtils.isEmpty(vo.getThickness()) && StringUtils.isEmpty(vo.getSealLeft())
                    && StringUtils.isEmpty(vo.getSealRight()) && StringUtils.isEmpty(vo.getSealUp()) && StringUtils.isEmpty(vo.getSealDown())) {

                flag = false;
                errList.add("小板轮廓数据不能为空");
            } else { // 成品长、成品宽、拆单长、拆单宽、厚、左封边、右封边、上封边、下封边 数据类型以及长度验证
                if (!convertToDouble(vo.getHeight())) {
                    flag = false;
                    errList.add("成品长数据类型错误");
                } else {
                    if (!checkPrecision(vo.getHeight())) {
                        flag = false;
                        errList.add("成品长数据长度错误");
                    }
                }
                if (!convertToDouble(vo.getWidth())) {
                    flag = false;
                    errList.add("成品宽数据类型错误");
                } else {
                    if (!checkPrecision(vo.getWidth())) {
                        flag = false;
                        errList.add("成品宽数据长度错误");
                    }
                }
                if (!convertToDouble(vo.getSplitHeight())) {
                    flag = false;
                    errList.add("拆单长数据类型错误");
                } else {
                    if (!checkPrecision(vo.getSplitHeight())) {
                        flag = false;
                        errList.add("拆单长数据长度错误");
                    }
                }
                if (!convertToDouble(vo.getSplitWidth())) {
                    flag = false;
                    errList.add("拆单宽数据类型错误");
                } else {
                    if (!checkPrecision(vo.getSplitWidth())) {
                        flag = false;
                        errList.add("拆单宽数据长度错误");
                    }
                }
                if (!convertToDouble(vo.getThickness())) {
                    flag = false;
                    errList.add("厚数据类型错误");
                } else {
                    if (!checkPrecision(vo.getThickness())) {
                        flag = false;
                        errList.add("厚数据长度错误");
                    }
                }
                if (!convertToDouble(vo.getSealLeft())) {
                    flag = false;
                    errList.add("左封边数据类型错误");
                } else {
                    if (!checkPrecision(vo.getSealLeft())) {
                        flag = false;
                        errList.add("左封边数据长度错误");
                    }
                }
                if (!convertToDouble(vo.getSealRight())) {
                    flag = false;
                    errList.add("右封边数据类型错误");
                } else {
                    if (!checkPrecision(vo.getSealRight())) {
                        flag = false;
                        errList.add("右封边数据长度错误");
                    }
                }
                if (!convertToDouble(vo.getSealUp())) {
                    flag = false;
                    errList.add("上封边数据类型错误");
                } else {
                    if (!checkPrecision(vo.getSealUp())) {
                        flag = false;
                        errList.add("上封边数据长度错误");
                    }
                }
                if (!convertToDouble(vo.getSealDown())) {
                    flag = false;
                    errList.add("下封边数据类型错误");
                } else {
                    if (!checkPrecision(vo.getSealDown())) {
                        flag = false;
                        errList.add("下封边数据长度错误");
                    }
                }
            }
            // 排版面、纹路、开门方向
            if (StringUtils.isEmpty(vo.getTypographicFace()) && StringUtils.isEmpty(vo.getTexture()) && StringUtils.isEmpty(vo.getOpenDoorType())) {
                flag = false;
                errList.add("排版面、纹路、开门方向不能为空");
            } else {
                DictDataRespDTO typographyDTO = dictDataApi.parseDictData(DictTypeConstants.TYPOGRAPHY_TYPE, vo.getTypographicFace()).getData();// 排版面
                if (typographyDTO == null) {
                    flag = false;
                    errList.add("排版面数据不存在");
                } else {
                    vo.setTypographicFace(typographyDTO.getValue());
                }
                DictDataRespDTO grainDTO = dictDataApi.parseDictData(DictTypeConstants.GRAIN_TYPE, vo.getTexture()).getData();// 纹路
                if (grainDTO == null) {
                    flag = false;
                    errList.add("纹路数据不存在");
                } else {
                    vo.setTexture(grainDTO.getValue());
                }
                DictDataRespDTO doorDTO = dictDataApi.parseDictData(DictTypeConstants.DOOR_OPENING_DIRECTIONS, vo.getOpenDoorType()).getData();
                if (doorDTO == null) {
                    flag = false;
                    errList.add("开门方向数据不存在");
                } else {
                    vo.setOpenDoorType(doorDTO.getValue());
                }
            }
        }

        if (!flag) {
            isErr++;
        }
        JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(errList));// 错误列表
        vo.setResult(String.valueOf(jsonArray));
        return flag;
    }

    // 数据类型可否转换判断
    public Boolean convertToDouble(String str) {
        try {
            Double.parseDouble(str);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    // 数据长度判断
    public boolean checkPrecision(String numberStr) {
        if (numberStr == null) {
            return false;
        }

        // 分割整数部分和小数部分
        String[] parts = numberStr.split("\\.");
        String integerPart = parts[0];
        String decimalPart = parts.length > 1 ? parts[1] : "";

        // 检查整数部分位数
        if (integerPart.length() > 5) {
            return false;
        }

        // 检查小数部分位数
        if (decimalPart.length() > 3) {
            return false;
        }
        return true;
    }

    public int isErr() {
        return isErr;
    }

    public void setErr(int isErr) {
        this.isErr = isErr;
    }
}
