package com.seer.teach.teacher.common.utils;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.CRC32;

/**
 * <p>
 *
 * </p>
 *
 * @author Captain
 * @since 2025-07-23 11:16
 */
public class TeacherUtils {

    /**
     * 批改类型标识
     */
    public static final int SSE_TYPE_CORRECT = 0;

    /**
     * 聊天类型标识
     */
    public static final int SSE_TYPE_CHAT = 1;

    /**
     * 学习类型标识
     */
    public static final int SSE_TYPE_STUDY = 2;


    private static final Pattern HTML_TAG_PATTERN = Pattern.compile("<[^>]*>");

    /**
     * 去除字符串中的所有 HTML 标签
     * @param input 原始字符串
     * @return 去掉 HTML 标签后的字符串
     */
    public static String removeHtmlTags(String input) {
        if (input == null || input.isEmpty()) {
            return input;
        }
        // 先去掉 script 和 style 内容
        String noScript = input.replaceAll("(?i)<script[^>]*?>[\\s\\S]*?</script>", "");
        String noStyle = noScript.replaceAll("(?i)<style[^>]*?>[\\s\\S]*?</style>", "");
        // 再去掉所有 HTML 标签
        String result = HTML_TAG_PATTERN.matcher(noStyle).replaceAll("");
        // 去掉多余空格和换行
        return result.trim();
    }

    /**
     * 将秒数转换为文本格式“用时 xx min”
     * 计算逻辑：将秒数换算为分钟，并进行四舍五入
     *
     * @param seconds  传入的时间（单位：秒）
     * @return         格式化后的文本 "用时 xx min"
     */
    public static String formatDuration(int seconds) {
        // 将秒转换为分钟，并进行四舍五入
        int minutes = (int) Math.round(seconds / 60.0);

        return "用时 " + minutes + " min";
    }

    /**
     * 将Base64编码的字符串转换为MultipartFile对象
     *
     * @param base64 Base64编码的字符串，可能包含数据URI前缀（如data:image/png;base64,）
     * @return 转换后的MultipartFile对象
     * @throws RuntimeException 当Base64解码失败时抛出运行时异常
     */
    public static MultipartFile base64ToMultipart(String base64) {
        try {
            String[] baseStrs = base64.split(",");
            byte[] bytes;

            // 处理带有数据URI前缀的Base64字符串（如data:image/png;base64,xxx）
            if (baseStrs.length > 1) {
                bytes = Base64.getDecoder().decode(baseStrs[1]);
            } else {
                // 处理纯Base64字符串
                bytes = Base64.getDecoder().decode(base64);
            }

            return new Base64DecodedMultipartFile(bytes);
        }catch (Exception e){
            throw new RuntimeException("Base64转换Multipart失败");
        }
    }


    /**
     * 将阿拉伯数字转换为中文数字（支持 1~99）
     */
    public static String toChineseNumber(int num) {
        String[] cnNums = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
        String[] cnUnits = {"", "十", "百", "千"};
        if (num < 10) {
            return cnNums[num];
        } else if (num < 20) {
            return "十" + (num % 10 == 0 ? "" : cnNums[num % 10]);
        } else if (num < 100) {
            int tens = num / 10;
            int ones = num % 10;
            return cnNums[tens] + "十" + (ones == 0 ? "" : cnNums[ones]);
        } else {
            return String.valueOf(num);
        }
    }

    /**
     * 根据传入的请求参数生成带时间戳的会话ID
     *
     * @param reqParams 可变参数列表，用于生成会话ID的输入参数
     * @return 基于CRC32算法与时间戳生成的会话ID，返回绝对值形式的整数
     */
    public static Integer generateSessionId(Object... reqParams) {
        CRC32 crc32 = new CRC32();
        StringBuilder sb = new StringBuilder();

        // 拼接所有非空参数
        for (Object param : reqParams) {
            if (param != null) {
                sb.append(param).append("|");
            }
        }

        // 加入当前时间戳，确保每次生成的结果唯一
        sb.append(System.currentTimeMillis());

        // 使用CRC32算法计算哈希值
        crc32.update(sb.toString().getBytes(StandardCharsets.UTF_8));
        return Math.abs((int) crc32.getValue());
    }


    /**
     * 获取当前时间
     *
     * @return LocalDateTime 当前时间
     */
    public static LocalDateTime now() {
        return LocalDateTime.now();
    }

    /**
     * 获取 n 分钟之前的时间
     *
     * @param minutes 分钟数
     * @return LocalDateTime n 分钟之前
     */
    public static LocalDateTime minutesAgo(long minutes) {
        return LocalDateTime.now().minusMinutes(minutes);
    }

    /**
     * 计算错误题目数量
     *
     * @param correctRate   正确率 (BigDecimal，取值范围 0~1)
     * @param questionCount 题目总数 (Integer)
     * @return 错误题目数量 (int)
     */
    public static int getErrorCount(BigDecimal correctRate, Integer questionCount) {
        if (correctRate == null || questionCount == null) {
            return 0;
        }

        // 计算正确数量 = 正确率 * 总题目数
        BigDecimal correctCount = correctRate.multiply(BigDecimal.valueOf(questionCount));

        // 四舍五入取整
        int correct = correctCount.setScale(0, RoundingMode.HALF_UP).intValue();

        // 错误数量 = 总数 - 正确数
        return questionCount - correct;
    }

    /**
     * 将字符串形式的 LocalDateTime 转换为 "M月d日" 格式
     *
     * @param dateTimeStr 形如 "2025-08-12T19:00:00" 的 LocalDateTime 字符串
     * @return 格式化后的日期字符串，如 "8月12日"
     */
    public static String formatTimestampToMonthDay(String dateTimeStr) {
        LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M月d日");
        return dateTime.format(formatter);
    }

    /**
     * 计算播放进度（当前时间 / 总时间）
     *
     * @param totalAudioDuration   总时长（秒）
     * @param currentAudioDuration 当前播放时长（秒）
     * @return 播放进度（0-1之间的小数，保留4位小数）
     */
    public static BigDecimal calculateProgress(Integer totalAudioDuration, Integer currentAudioDuration) {
        if (totalAudioDuration == null || currentAudioDuration == null || totalAudioDuration == 0) {
            return BigDecimal.ZERO;
        }

        return new BigDecimal(currentAudioDuration)
                .divide(new BigDecimal(totalAudioDuration), 4, RoundingMode.HALF_UP);
    }

    /**
     * 计算百分比 (返回整数 0~100)
     *
     * @param total   总时长/总数
     * @param current 当前时长/数量
     * @return 百分比整数，例如 75 表示 75%
     */
    public static Integer calculatePercentage(Integer total, Integer current) {
        if (total == null || current == null || total == 0) {
            return 0;
        }
        return (int) Math.round(current * 100.0 / total);
    }


    /**
     * 将给定的BigDecimal数值除以100
     *
     * @param score 需要除以100的数值，如果为null则返回0
     * @return 除以100后的结果，保留2位小数，向下舍入
     */
    public static BigDecimal divideBy100(BigDecimal score) {
        // 如果输入值为null，返回0
        if (score == null) {
            return BigDecimal.ZERO;
        }
        // 将数值除以100，保留2位小数，采用向下舍入模式
        return score.divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN);
    }

    /**
     * 计算正确率（0~1之间的BigDecimal，保留4位小数），适配 Decimal(5,4)
     *
     * @param total   总题数（必须大于0）
     * @param correct 正确题数
     * @return 正确率（如 0.9080 表示 90.8%）
     */
    public static BigDecimal calculateAccuracy(int total, int correct) {
        if (total <= 0) {
            return BigDecimal.ZERO;
        }

        BigDecimal totalDecimal = BigDecimal.valueOf(total);
        BigDecimal correctDecimal = BigDecimal.valueOf(correct);

        // 计算比例，保留 4 位小数，四舍五入
        return correctDecimal.divide(totalDecimal, 4, RoundingMode.HALF_UP);
    }

    /**
     * 将正确率（如 0.9080）转换为百分比字符串，保留1位小数
     *
     * @param accuracy 正确率（0~1之间的BigDecimal）
     * @return 百分比字符串（如 "90.8%"）
     */
    public static String formatAccuracyPercentage(BigDecimal accuracy) {
        return accuracy.multiply(BigDecimal.valueOf(100))
                .setScale(1, RoundingMode.HALF_UP)
                .toPlainString() + "%";
    }

    /**
     * 根据给定的数量返回对应数量的选项，选项顺序符合26个英文字母（大写）。
     *
     * @param count 需要返回的选项数量
     * @return List<String> 包含对应数量选项的列表
     */
    public static List<String> getOptions(int count) {
        // 如果 count 为 0，直接返回空的 List
        if (count == 0) {
            return Collections.emptyList();
        }

        if (count < 1 || count > 26) {
            throw new IllegalArgumentException("选项数量必须在1到26之间");
        }

        // 生成顺序字母（从 A 开始）
        return new ArrayList<String>(count) {{
            for (int i = 0; i < count; i++) {
                add(String.valueOf((char) ('A' + i)));
            }
        }};
    }

    /**
     * 格式化数字，单位为 K（千）或 W（万）
     *
     * @param number 原始整数
     * @return 格式化后的字符串，带单位
     */
    public static String formatNumber(int number) {
        if (number >= 10000) {
            // 单位为 W（万）
            double wValue = number / 10000.0;
            return String.format("%.2fW", wValue);
        } else {
            // 单位为 K（千）
            double kValue = number / 1000.0;
            return String.format("%.2fK", kValue);
        }
    }

    /**
     * 获取当前时间，类型为 LocalDateTime，精确到秒
     *
     * @return 当前时间，精确到秒
     */
    public static LocalDateTime getCurrentTimeToSecond() {
        return LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS);
    }


    /**
     * Author: Captain
     * Desc:   判断给定的 LocalDateTime 是否是今天的数据
     * Params: [timestamp] 本地时间对象
     * Return: boolean，true 表示是今天的数据，false 表示不是
     * Time: 2025/5/26 20:34
     */
    public static boolean isToday(LocalDateTime timestamp) {
        LocalDate today = LocalDate.now(ZoneId.systemDefault());
        return timestamp.toLocalDate().equals(today);
    }

    /**
     * 截取内容字符串的前75个字符，如果为空或长度不足则直接返回原内容，
     * 超出部分追加省略号“...”
     *
     * @param content 原始内容字符串
     * @return 截取后的简略内容
     */
    public static String getBriefCOntent(String content) {
        if (StringUtils.isBlank(content)) {
            return "";
        }
        return content.length() <= 75 ? content : content.substring(0, 75) + "...";
    }


    /**
     * Author: Captain
     * Desc:   将 LocalDateTime 时间格式化为 "HH点mm分ss秒" 格式的字符串
     * Params: [timestamp] LocalDateTime 类型的时间
     * Return: java.lang.String 格式化后的字符串
     * Time: 2025/5/26 9:23
     */
    public static String formatTimestampToTime(LocalDateTime timestamp) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH点mm分ss秒");
        return timestamp.format(formatter);
    }

    /**
     * Author: Captain
     * Desc:   将 LocalDateTime 转换成 "yyyy年MM月dd日" 格式的日期字符串
     * Params: [timestamp] LocalDateTime 类型的时间
     * Return: java.lang.String 格式化后的字符串
     * Time: 2025/5/26 9:20
     */
    public static String formatTimestampToDate(LocalDateTime timestamp) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        return timestamp.format(formatter);
    }

    /**
     * 将 BigDecimal 类型的小数转换成百分比字符串，保留两位小数
     *
     * @param decimal 小数字段，范围一般是0~1，比如0.0567
     * @return 百分比字符串，比如 "5.67%"
     */
    public static String toPercentage(BigDecimal decimal) {
        if (decimal == null) {
            return "0.00%";
        }
        DecimalFormat df = new DecimalFormat("0.00%");
        return df.format(decimal);
    }

    /**
     * 判断是否是小学年级
     * @param gradeId 年级ID
     * @return true 表示小学
     */
    public static Boolean isPrimary(int gradeId) {
        // 假设小学年级ID范围为 1~6
        return gradeId >= 1 && gradeId <= 6;
    }

    /**
     * 判断是否是初中年级
     * @param gradeId 年级ID
     * @return true 表示初中
     */
    public static Boolean isJunior(int gradeId) {
        // 假设初中年级ID范围为 7~9
        return gradeId >= 7 && gradeId <= 9;
    }

    /**
     * 判断是否是高中年级
     * @param gradeId 年级ID
     * @return true 表示高中
     */
    public static Boolean isSenior(int gradeId) {
        // 假设高中年级ID范围为 10~12
        return gradeId >= 10 && gradeId <= 12;
    }

}
