package jnpf.cultivate.v2.util;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import jnpf.entity.cultivate.CultivateIdentifyApplyDetailsBackups;
import jnpf.entity.cultivate.CultivateIdentifyApplyTableBackups;
import jnpf.entity.cultivate.CultivateIdentifyItems;
import jnpf.enums.AppraisalScoreTypeEnum;
import jnpf.enums.cultivate.ApplyResultEnum;
import jnpf.enums.cultivate.ApplyTypeEnum;
import jnpf.enums.cultivate.IdentifyScoreTypeEnum;
import jnpf.model.cultivate.po.FtbCultivateIdentifyCategories;
import jnpf.model.cultivate.po.FtbCultivateIdentifyItemsPool;
import jnpf.model.cultivate.v2.apply.req.V2IdentifyApplyItemReq;
import jnpf.model.cultivate.v2.identify.req.V2IdentifyItemsImportSaveReq;
import jnpf.model.cultivate.v2.identify.req.V2IdentifyTableImportSaveReq;
import jnpf.model.cultivate.v2.identify.vo.V2IdentifyScoreConfigVo;
import jnpf.model.cultivate.v2.identify.vo.V2IdentifyTableScoreConfigVo;
import jnpf.model.cultivate.v2.identify.vo.V2PreIdentifyErrorVo;
import jnpf.model.cultivate.v2.item_pool.vo.V2IdentifyItemVo;
import jnpf.model.cultivate.v2.label.vo.FtbCultivateLabelVo;
import jnpf.util.StringUtil;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class CultivateIdentityUtil {

    public static MutablePair<Integer, String> calUserIdentifyResult(CultivateIdentifyApplyTableBackups table, BigDecimal totalScore, BigDecimal userTotalScore) {

        if (table.getScoreType().equals(IdentifyScoreTypeEnum.GRADE_SYSTEM.getCode())) {
            //计算合格分数
            BigDecimal qualifiedScore;
            if (table.getPassType().equals(ApplyTypeEnum.GDF.getCode())) {
                qualifiedScore = table.getPassScore();
            } else {
                qualifiedScore = totalScore.multiply(table.getPassScore().divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
            }
            //计算优秀分数
            BigDecimal excellentScore;
            if (table.getExcellentType().equals(ApplyTypeEnum.GDF.getCode())) {
                excellentScore = table.getExcellentScore();
            } else {
                excellentScore = totalScore.multiply(table.getExcellentScore().divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
            }
            if (userTotalScore.compareTo(qualifiedScore) < 0) {
                return MutablePair.of(ApplyResultEnum.BHG.getCode(), "");
            } else if (userTotalScore.compareTo(qualifiedScore) >= 0 && userTotalScore.compareTo(excellentScore) < 0) {
                return MutablePair.of(ApplyResultEnum.HG.getCode(), "");
            } else if (userTotalScore.compareTo(excellentScore) >= 0) {
                return MutablePair.of(ApplyResultEnum.YX.getCode(), "");
            }
        } else {
            String scoreConfig = table.getScoreConfig();
            if (StringUtil.isEmpty(scoreConfig)) {
                return MutablePair.of(ApplyResultEnum.BHG.getCode(), "");
            }
            List<V2IdentifyTableScoreConfigVo> configVoList = JSON.parseArray(table.getScoreConfig(), V2IdentifyTableScoreConfigVo.class);
            if (CollUtil.isEmpty(configVoList)) {
                return MutablePair.of(ApplyResultEnum.BHG.getCode(), "");
            }
            int maxIndex = configVoList.size() - 1;
            for (int i = 0; i < configVoList.size(); i++) {
                V2IdentifyTableScoreConfigVo configVo = configVoList.get(i);
                if (i == 0) {
                    if (userTotalScore.compareTo(new BigDecimal(configVo.getMin())) >= 0) {
                        return MutablePair.of(configVo.getResult(), configVo.getLevelName());
                    }
                } else if (maxIndex == i) {
                    if (userTotalScore.compareTo(new BigDecimal(configVo.getMax())) <= 0) {
                        return MutablePair.of(configVo.getResult(), configVo.getLevelName());
                    }
                } else {
                    if (userTotalScore.compareTo(new BigDecimal(configVo.getMin())) >= 0 && userTotalScore.compareTo(new BigDecimal(configVo.getMax())) <= 0) {
                        return MutablePair.of(configVo.getResult(), configVo.getLevelName());
                    }
                }
            }
            return MutablePair.of(ApplyResultEnum.BHG.getCode(), "");
        }
        return MutablePair.of(ApplyResultEnum.BHG.getCode(), "");
    }

    public static BigDecimal calUserTotalScore(List<V2IdentifyApplyItemReq> identifyItemList) {
        BigDecimal totalScore = new BigDecimal(0);
        for (V2IdentifyApplyItemReq applyItem : identifyItemList) {
            totalScore = totalScore.add(applyItem.getIdentifyScore());
        }
        return totalScore;
    }

    public static BigDecimal calIdentityTotalScore(List<CultivateIdentifyApplyDetailsBackups> identifyItemsList) {
        //计算鉴定总分
        BigDecimal totalScore = new BigDecimal(0);
        for (CultivateIdentifyApplyDetailsBackups applyDetails : identifyItemsList) {
            if (applyDetails.getType().equals(0)) {
                totalScore = totalScore.add(applyDetails.getScore());
            } else {
                totalScore = totalScore.add(new BigDecimal(applyDetails.getMaxScore()));
            }
        }
        return totalScore;
    }

    /**
     * 构建鉴定项重复判断的唯一标识
     *
     * @param item 鉴定项信息
     * @return 重复判断的唯一标识字符串
     */
    public static String buildRepeatKey(FtbCultivateIdentifyItemsPool item) {
        StringBuilder sb = new StringBuilder();
        sb.append(item.getName())
                .append(item.getType());

        if (item.getType().equals(AppraisalScoreTypeEnum.FLOATING.getCode())) {
            sb.append(item.getMinScore())
                    .append(item.getMaxScore());
        } else if (item.getType().equals(AppraisalScoreTypeEnum.FIXED.getCode())) {
            sb.append(item.getTotalScore());
        }

        return sb.toString();
    }

    public static String buildRepeatKey(V2IdentifyItemsImportSaveReq item) {
        StringBuilder sb = new StringBuilder();
        sb.append(item.getName())
                .append(item.getType());

        if (item.getType().equals(AppraisalScoreTypeEnum.FLOATING.getCode())) {
            sb.append(item.getMinScore())
                    .append(item.getMaxScore());
        } else if (item.getType().equals(AppraisalScoreTypeEnum.FIXED.getCode())) {
            sb.append(item.getScore());
        }

        return sb.toString();
    }

    /**
     * 构建鉴定项重复判断的唯一标识
     *
     * @param item 鉴定项信息
     * @return 重复判断的唯一标识字符串
     */
    public static String buildRepeatKey(V2IdentifyItemVo item) {
        StringBuilder sb = new StringBuilder();
        sb.append(item.getItemName())
                .append(item.getType());

        if (item.getType().equals(AppraisalScoreTypeEnum.FLOATING.getCode())) {
            sb.append(item.getMinScore())
                    .append(item.getMaxScore());
        } else if (item.getType().equals(AppraisalScoreTypeEnum.FIXED.getCode())) {
            sb.append(item.getTotalScore());
        }

        return sb.toString();
    }

    public static void parseAndValidateScore(V2IdentifyItemVo itemVo) {
        String scoreStr = itemVo.getScore().trim();

        // 检查是否包含 ~ 或 - 分隔符
        if (scoreStr.contains("~") || scoreStr.contains("-")) {
            // 使用相应的分隔符分割
            String[] parts = scoreStr.contains("~") ?
                    scoreStr.split("~") : scoreStr.split("-");

            if (parts.length != 2) {
                itemVo.setMsg("分值格式错误，请使用'最小值~最大值'或'最小值-最大值'格式");
                itemVo.setSuccess(1);
                return;
            }

            try {
                String minStr = parts[0].trim();
                String maxStr = parts[1].trim();

                // 检查是否为数字
                if (!isNumeric(minStr) || !isNumeric(maxStr)) {
                    itemVo.setMsg("分值必须为数字");
                    itemVo.setSuccess(1);
                    return;
                }

                int minScore = Integer.parseInt(minStr);
                int maxScore = Integer.parseInt(maxStr);

                // 验证数值范围
                if (minScore < 0 || minScore > 100 || maxScore < 0 || maxScore > 100) {
                    itemVo.setMsg("分值应在0-100范围内");
                    itemVo.setSuccess(1);
                    return;
                }

                if (minScore >= maxScore) {
                    itemVo.setMsg("浮动分前值应小于后值");
                    itemVo.setSuccess(1);
                    return;
                }

                // 设置浮动分值
                itemVo.setType(AppraisalScoreTypeEnum.FLOATING.getCode());
                itemVo.setMinScore(minScore);
                itemVo.setMaxScore(maxScore);
                itemVo.setSuccess(0);
                itemVo.setMsg(null);

            } catch (NumberFormatException e) {
                itemVo.setMsg("分值格式不正确");
                itemVo.setSuccess(1);
            }
        } else {
            // 单个分值
            try {
                if (!isNumeric(scoreStr)) {
                    itemVo.setMsg("分值必须为数字");
                    itemVo.setSuccess(1);
                    return;
                }

                int totalScore = Integer.parseInt(scoreStr);

                if (totalScore < 0 || totalScore > 100) {
                    itemVo.setMsg("分值应在0-100范围内");
                    itemVo.setSuccess(1);
                    return;
                }

                // 设置固定分值
                itemVo.setType(AppraisalScoreTypeEnum.FIXED.getCode());
                itemVo.setTotalScore(totalScore);
                itemVo.setSuccess(0);
                itemVo.setMsg(null);

            } catch (NumberFormatException e) {
                itemVo.setMsg("分值格式不正确");
                itemVo.setSuccess(1);
            }
        }
    }

    /**
     * 判断字符串是否为数字（包括整数和小数）
     *
     * @param str 待判断的字符串
     * @return 是否为数字 true-是、false-否
     */
    public static boolean isNumeric(String str) {
        if (str == null || str.trim().isEmpty()) {
            return false;
        }
        return str.matches("-?\\d+(\\.\\d+)?");
    }


    /**
     * 逐行读取不规则表格数据
     *
     * @param inputStream
     * @return 包含所有行数据的列表，每行是一个字符串列表
     */
    public static List<List<String>> readIrregularExcelRowByRow(InputStream inputStream) throws IOException {
        List<List<String>> allRows = new ArrayList<>();

        try (Workbook workbook = new XSSFWorkbook(inputStream)) {
            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表
            for (Row row : sheet) {
                List<String> rowData = new ArrayList<>();
                // 处理每一行的单元格
                for (Cell cell : row) {
                    String cellValue = getCellValueAsString(cell);
                    rowData.add(cellValue.trim());
                }
                // 只添加非空行（可根据业务需求调整）
                if (!isRowEmpty(rowData)) {
                    allRows.add(rowData);
                }
            }
        }

        return allRows;
    }

    /**
     * 将单元格值转换为字符串
     */
    public static String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return "";
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    // 处理数字，避免科学计数法
                    return String.valueOf((long) cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            case BLANK:
                return "";
            default:
                return "";
        }
    }

    /**
     * 检查行是否为空（所有单元格都为空）
     */
    public static boolean isRowEmpty(List<String> rowData) {
        for (String cellValue : rowData) {
            if (cellValue != null && !cellValue.trim().isEmpty()) {
                return false;
            }
        }
        return true;
    }


    public static V2IdentifyTableImportSaveReq convertExcelData(List<List<String>> lists,
                                                                List<FtbCultivateIdentifyCategories> itemCateList,
                                                                List<FtbCultivateLabelVo> labelVoList,
                                                                long oldTableNum,
                                                                List<FtbCultivateIdentifyItemsPool> poolList
    ) {

        Map<String, FtbCultivateIdentifyCategories> itemCateMap = itemCateList.stream().collect(Collectors.toMap(FtbCultivateIdentifyCategories::getName, item -> item));
        Map<String, FtbCultivateLabelVo> labelMap = labelVoList.stream().collect(Collectors.toMap(FtbCultivateLabelVo::getName, item -> item));
        checkParams(lists);
        V2IdentifyTableImportSaveReq req = new V2IdentifyTableImportSaveReq();
        List<V2PreIdentifyErrorVo> errorVoList = req.getPreIdentifyImportVo().getItemList();
        String tableName = lists.get(0).get(1);
        if (StringUtil.isEmpty(tableName)) {
            errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第1行").msg("鉴定表名称不能为空").build());
        }
        //增加鉴定表名称长度不超哥20个字
        if (tableName.length() > 20) {
            errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第1行").msg("鉴定表名称不能超过20个字").build());
        }
        if (oldTableNum > 0) {
            errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第1行").msg("鉴定表名称已经在系统中存在").build());
        }

        req.setName(tableName);
        String tableLabelId = lists.get(1).get(1);
        if (StringUtil.isEmpty(tableLabelId)) {
            errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第2行").msg("鉴定表标签不能为空").build());
        } else {
            FtbCultivateLabelVo ftbCultivateLabelVo = labelMap.get(tableLabelId);
            if (ftbCultivateLabelVo == null) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第2行").msg("鉴定表标签不存在").build());
            } else {
                req.setLabelId(ftbCultivateLabelVo.getId());
            }
        }
        req.setScoreType(IdentifyScoreTypeEnum.GRADE_SYSTEM.getCode());
        String passScoreStr = lists.get(3).get(1);
        if (StringUtil.isEmpty(passScoreStr)) {
            errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第4行").msg("鉴定合格分数不能为空").build());
        } else {
            if (!CultivateIdentityUtil.isNumeric(passScoreStr)) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第4行").msg("鉴定合格分数必须是数字").build());
            } else {
                req.setPassScore(new BigDecimal(passScoreStr));
                req.setPassType(1);
            }
        }
        String excellentScoreStr = lists.get(4).get(1);
        if (StringUtil.isEmpty(excellentScoreStr)) {
            errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第5行").msg("鉴定优秀分数不能为空").build());
        } else {
            if (!CultivateIdentityUtil.isNumeric(excellentScoreStr)) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第5行").msg("鉴定优秀分数必须是数字").build());
            } else {
                req.setExcellentScore(new BigDecimal(excellentScoreStr));
                req.setExcellentType(1);
            }
        }
        Map<String, String> dbContentCateIdMap = new HashMap<>();
        for (FtbCultivateIdentifyItemsPool itemsPool : poolList) {
            String s = CultivateIdentityUtil.buildRepeatKey(itemsPool);
            dbContentCateIdMap.put(s, itemsPool.getCateId());
        }

        List<V2IdentifyItemsImportSaveReq> identifyItemList = new ArrayList<>();
        Integer totalScore = 0;
        List<String> itemNameList = new ArrayList<>();
        for (int i = 6; i < lists.size(); i++) {
            V2IdentifyItemsImportSaveReq item = new V2IdentifyItemsImportSaveReq();
            List<String> rowData = lists.get(i);
            if (isRowEmpty(rowData)) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg("鉴定项数据不能为空").build());
                continue;
            }
            String numStr = rowData.get(0);
            if (StringUtil.isEmpty(numStr)) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg("鉴定项编号不能为空").build());
                continue;
            }
            try {
                item.setSortCode(Integer.parseInt(numStr));
            } catch (Exception e) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg("鉴定项编号必须是数字").build());
                continue;
            }
            String name = rowData.get(1);
            if (StringUtil.isEmpty(name)) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg("鉴定项内容不能为空").build());
                continue;
            }
            // 鉴定项内容长度不能超过500个字
            if (name.length() > 500) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg("鉴定项内容长度不能超过500个字").build());
                continue;
            }
            item.setName(name);

            String itemCateId = rowData.get(2);
            if (StringUtil.isEmpty(itemCateId)) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg("鉴定项分类不能为空").build());
                continue;
            }
            FtbCultivateIdentifyCategories itemCate = itemCateMap.get(itemCateId);
            if (itemCate == null) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg("鉴定项分类不存在").build());
                continue;
            }
            item.setCateId(itemCate.getId());

            V2IdentifyItemVo v2IdentifyItemVo = new V2IdentifyItemVo();
            v2IdentifyItemVo.setScore(rowData.get(3));

            parseAndValidateScore(v2IdentifyItemVo);
            if (v2IdentifyItemVo.getSuccess().equals(1)) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg(v2IdentifyItemVo.getMsg()).build());
                continue;
            }
            item.setType(v2IdentifyItemVo.getType());
            if (item.getType().equals(AppraisalScoreTypeEnum.FIXED.getCode())) {
                item.setScore(new BigDecimal(v2IdentifyItemVo.getTotalScore()));
                totalScore += item.getScore().intValue();
            } else {
                item.setMinScore(v2IdentifyItemVo.getMinScore());
                item.setMaxScore(v2IdentifyItemVo.getMaxScore());
                totalScore += item.getMaxScore();
            }

            String repeat = CultivateIdentityUtil.buildRepeatKey(item);
            if (itemNameList.contains(repeat)) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg("鉴定项内容和分数重复").build());
            }
            String s = dbContentCateIdMap.get(repeat);
            if (s != null && !s.equals(item.getCateId())) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第" + (i + 1) + "行").msg("鉴定项中的分类和数据库中存在的分类不一致").build());
            }
            itemNameList.add(repeat);
            identifyItemList.add(item);
        }
        if (req.getPassScore() != null && req.getExcellentScore() != null) {
            if (req.getPassScore().intValue() >= req.getExcellentScore().intValue()) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第5行").msg("鉴定合格分数不能大于等于鉴定优秀分数").build());
            }
        }
        if (req.getPassScore() != null) {
            if (req.getPassScore().intValue() >= totalScore) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第4行").msg("鉴定合格分数不能大于等于鉴定总分").build());
            }
        }
        if (req.getExcellentScore() != null) {
            if (req.getExcellentScore().intValue() > totalScore) {
                errorVoList.add(V2PreIdentifyErrorVo.builder().alt("第5行").msg("鉴定优秀分数不能大于鉴定总分").build());
            }
        }

        req.setIdentifyItemList(identifyItemList);
        return req;
    }

    private static void checkParams(List<List<String>> lists) {
        if (lists == null || lists.isEmpty()) {
            throw new RuntimeException("请上传正确的模版数据");
        }
        if (lists.size() < 6) {
            throw new RuntimeException("请上传正确模版数据");
        }
        if (!lists.get(0).get(0).equals("鉴定表名称")) {
            throw new RuntimeException("上传的模版不正确");
        }
        if (!lists.get(1).get(0).equals("鉴定表标签")) {
            throw new RuntimeException("上传的模版不正确");
        }
        if (!lists.get(2).get(0).equals("鉴定总分")) {
            throw new RuntimeException("上传的模版不正确");
        }
        if (!lists.get(3).get(0).equals("鉴定合格分数")) {
            throw new RuntimeException("上传的模版不正确");
        }
        if (!lists.get(4).get(0).equals("鉴定优秀分数")) {
            throw new RuntimeException("上传的模版不正确");
        }
        if (!lists.get(5).get(0).equals("鉴定项序号") ||
                !lists.get(5).get(1).equals("鉴定项内容") ||
                !lists.get(5).get(2).equals("鉴定项分类") ||
                !lists.get(5).get(3).equals("分值")) {
            throw new RuntimeException("上传的模版不正确");
        }
    }

    public static V2IdentifyScoreConfigVo calPassAndExcellentResult(BigDecimal totalScore, CultivateIdentifyApplyTableBackups table) {
        V2IdentifyScoreConfigVo vo = new V2IdentifyScoreConfigVo();
        vo.setCalTotalScore(totalScore);
        vo.setScoreType(table.getScoreType());
        if (table.getScoreType().equals(IdentifyScoreTypeEnum.GRADE_SYSTEM.getCode())) {
            //计算合格分数
            BigDecimal qualifiedScore;
            if (table.getPassType().equals(ApplyTypeEnum.GDF.getCode())) {
                qualifiedScore = table.getPassScore();
            } else {
                qualifiedScore = totalScore.multiply(table.getPassScore().divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
            }
            //计算优秀分数
            BigDecimal excellentScore;
            if (table.getExcellentType().equals(ApplyTypeEnum.GDF.getCode())) {
                excellentScore = table.getExcellentScore();
            } else {
                excellentScore = totalScore.multiply(table.getExcellentScore().divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP));
            }

            vo.setCalPassScore(qualifiedScore);
            vo.setCalExcellentScore(excellentScore);

        } else {
            List<V2IdentifyTableScoreConfigVo> configVoList = JSON.parseArray(table.getScoreConfig(), V2IdentifyTableScoreConfigVo.class);
            vo.setConfigVoList(configVoList);
        }
        return vo;
    }

    /**
     * 鉴定项内容重复
     *
     * @param item 鉴定表中的鉴定项
     * @return 重复的key
     */
    public static String buildRepeatKey(CultivateIdentifyItems item) {
        StringBuilder sb = new StringBuilder();
        sb.append(item.getName())
                .append(item.getType());

        if (item.getType().equals(AppraisalScoreTypeEnum.FLOATING.getCode())) {
            sb.append(item.getMinScore())
                    .append(item.getMaxScore());
        } else if (item.getType().equals(AppraisalScoreTypeEnum.FIXED.getCode())) {
            sb.append(item.getScore());
        }

        return sb.toString();
    }
}
