package com.hzs.member.statis.util;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.hzs.common.core.constant.SysConstants;
import com.hzs.common.domain.member.statis.DirectStatisticsTop30VO;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class DataGeneratorUtils {

    // 时间粒度枚举
    public enum TimeGranularity {
        DAY,    // 按天
        HOUR    // 按小时
    }
    private static final String prefix = "BD";

    // 常见姓氏数组
    private static final String[] COMMON_SURNAMES = {
        "王", "李", "张", "刘", "陈", "杨", "黄", "赵", "吴", "周",
        "徐", "孙", "马", "朱", "胡", "郭", "何", "高", "林", "罗",
        "郑", "梁", "谢", "宋", "唐", "许", "韩", "冯", "邓", "曹",
        "彭", "曾", "肖", "田", "董", "袁", "潘", "于", "蒋", "蔡"
    };

    // 当前种子，用于生成数据
    private static int currentSeed = getSeed(TimeGranularity.DAY); // 默认按天
    private static TimeGranularity currentGranularity = TimeGranularity.DAY;
    // 预先生成的30条基础数据
    private static List<DirectStatisticsTop30VO> PERIODIC_PRE_GENERATED_DATA = generatePeriodicPredefinedData();

    /**
     * 生成假数据并添加到列表中
     *
     * @param list          已有数据列表
     * @param totalCount    需要生成的总数据量
     * @param type          类型：1为设置numberOfPeople，2为设置numberOfAmount
     * @param granularity   时间粒度：DAY按天，HOUR按小时
     * @return 包含新生成数据的列表
     */
    public static List<DirectStatisticsTop30VO> generateFakeData(
            List<DirectStatisticsTop30VO> list, int totalCount, int type, TimeGranularity granularity) {
        // 检查时间是否已变化，如果变化则重新生成数据
        checkAndUpdatePeriodicData(granularity);

        // 创建返回列表（复制原列表，避免修改原列表）
        List<DirectStatisticsTop30VO> resultList = new ArrayList<>(list);

        // 如果总数小于等于已有列表大小，直接返回原列表
        if (totalCount <= list.size()) {
            return resultList;
        }

        // 需要生成的新数据数量
        int needGenerateCount = totalCount - list.size();

        // 从预生成数据中获取所需数量的数据
        List<DirectStatisticsTop30VO> newData = getPeriodicPreGeneratedDataByCount(needGenerateCount, type);

        // 添加新数据到结果列表
        resultList.addAll(newData);

        // 按照对应字段降序排序
        if (type == 1) {
            resultList.sort((a, b) -> b.getNumberOfPeople().compareTo(a.getNumberOfPeople()));
        } else if (type == 2) {
            resultList.sort((a, b) -> b.getNumberOfAmount().compareTo(a.getNumberOfAmount()));
        }

        return resultList;
    }

    /**
     * （兼容旧版本）按天生成数据
     */
    public static List<DirectStatisticsTop30VO> generateFakeData(
            List<DirectStatisticsTop30VO> list, int totalCount, int type) {
        return generateFakeData(list, totalCount, type, TimeGranularity.DAY);
    }

    /**
     * 检查时间是否已变化，如果变化则更新数据
     */
    private static void checkAndUpdatePeriodicData(TimeGranularity granularity) {
        int newSeed = getSeed(granularity);
        if (newSeed != currentSeed || granularity != currentGranularity) {
            currentSeed = newSeed;
            currentGranularity = granularity;
            PERIODIC_PRE_GENERATED_DATA = generatePeriodicPredefinedData();
        }
    }

    /**
     * 根据时间粒度获取种子
     * @param granularity 时间粒度
     * @return 对应的种子
     */
    private static int getSeed(TimeGranularity granularity) {
        if (granularity == TimeGranularity.HOUR) {
            // 按小时：格式为YYYYMMDDHH
            LocalDateTime now = LocalDateTime.now();
            return Integer.parseInt(now.format(DateTimeFormatter.ofPattern("yyyyMMddHH")));
        } else {
            // 按天：格式为YYYYMMDD
            LocalDate today = LocalDate.now();
            return Integer.parseInt(today.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        }
    }

    /**
     * 生成当前周期的30条预定义数据
     */
    private static List<DirectStatisticsTop30VO> generatePeriodicPredefinedData() {
        List<DirectStatisticsTop30VO> dataList = new ArrayList<>(30);

        // 使用当前周期的种子创建Random对象
        Random periodRandom = new Random(currentSeed);

        // 生成30条基础数据
        for (int i = 0; i < 30; i++) {
            DirectStatisticsTop30VO vo = new DirectStatisticsTop30VO();

            // 设置基础信息，包含时间粒度标识
            long baseId = 4000000L + currentSeed % 1000000L;
            vo.setMemberId(baseId + i);

            // 根据时间粒度生成不同的用户编号前缀
//            String prefix = currentGranularity == TimeGranularity.HOUR ? "HOUR" : "DAY";
//            String prefix = SysConstants.HAI_FUN_PREFIX;
            vo.setMemberCode(generateMemberCode(currentSeed, 10));

            // 生成随机中文姓名
            vo.setMemberName(generateRandomChineseName(i, periodRandom));

            // 使用周期随机数生成数据值
            vo.setNumberOfPeople(1 + periodRandom.nextInt(100)); // 1-100之间的随机值

            // 生成金额值
            BigDecimal amount = new BigDecimal(100 + periodRandom.nextInt(10000))
                    .add(new BigDecimal(periodRandom.nextDouble()))
                    .setScale(4, BigDecimal.ROUND_HALF_UP);
            vo.setNumberOfAmount(amount);

            dataList.add(vo);
        }

        return dataList;
    }
    public static String generateMemberCode(long currentSeed, int i) {
        int prefixLength = prefix.length();
        int numPartLength = 10 - prefixLength;
        long seedPart = generateRandomSeedPart(numPartLength);
        String memberCode = prefix + seedPart;
        return memberCode.length() > 10 ? memberCode.substring(0, 10) : memberCode;
    }
    /**
     * 生成指定位数的随机seedPart
     *
     * @param digits 位数
     * @return 随机数
     */
    private static long generateRandomSeedPart(int digits) {
        if (digits <= 0) {
            return 0;
        }

        // 计算最小值和最大值
        int min = (int) Math.pow(10, digits - 1);
        int max = (int) Math.pow(10, digits) - 1;

        // 如果digits为0，返回0
        if (min == 0 && max == 0) {
            return 0;
        }

        return RandomUtil.randomInt(min, max);
    }
    /**
     * 根据需要的数量从预生成数据中获取数据
     */
    private static List<DirectStatisticsTop30VO> getPeriodicPreGeneratedDataByCount(int count, int type) {
        List<DirectStatisticsTop30VO> result = new ArrayList<>(count);

        for (int i = 0; i < count; i++) {
            // 从预生成数据中循环获取
            DirectStatisticsTop30VO originalVo = PERIODIC_PRE_GENERATED_DATA.get(i % 30);

            // 创建副本以避免修改预生成的数据
            DirectStatisticsTop30VO newVo = new DirectStatisticsTop30VO();
            newVo.setMemberId(originalVo.getMemberId());
            newVo.setMemberName(originalVo.getMemberName());
            newVo.setMemberCode(originalVo.getMemberCode());

            // 根据类型设置相应的值
            if (type == 1) {
                // 类型1：设置numberOfPeople
                newVo.setNumberOfPeople(originalVo.getNumberOfPeople());
                newVo.setNumberOfAmount(BigDecimal.ZERO);
            } else if (type == 2) {
                // 类型2：设置numberOfAmount
                newVo.setNumberOfPeople(0);
                newVo.setNumberOfAmount(originalVo.getNumberOfAmount());
            }

            result.add(newVo);
        }

        return result;
    }

    /**
     * 生成随机中文姓名
     */
    private static String generateRandomChineseName(int index, Random random) {
        // 随机选择姓氏
        String surname = COMMON_SURNAMES[random.nextInt(COMMON_SURNAMES.length)];

        // 随机决定是二字姓名还是三字姓名
        boolean isTwoCharacters = random.nextBoolean();

        if (isTwoCharacters) {
            // 二字姓名：姓氏 + 1个随机汉字
            return surname + generateRandomChineseChar(random);
        } else {
            // 三字姓名：姓氏 + 2个随机汉字
            return surname + generateRandomChineseChar(random) + generateRandomChineseChar(random);
        }
    }

    /**
     * 生成随机汉字
     */
    private static char generateRandomChineseChar(Random random) {
        // 中文汉字Unicode范围大致在0x4E00到0x9FA5之间
        int start = 0x4E00;
        int end = 0x9FA5;
        return (char) (start + random.nextInt(end - start + 1));
    }

    /**
     * 获取当前周期预生成的30条完整数据
     * @param granularity 时间粒度
     * @return 预生成的数据列表
     */
    public static List<DirectStatisticsTop30VO> getPeriodicPreGeneratedData(TimeGranularity granularity) {
        // 检查时间是否已变化
        checkAndUpdatePeriodicData(granularity);

        // 返回预生成数据的副本，避免外部修改
        List<DirectStatisticsTop30VO> copyList = new ArrayList<>(PERIODIC_PRE_GENERATED_DATA.size());
        for (DirectStatisticsTop30VO vo : PERIODIC_PRE_GENERATED_DATA) {
            DirectStatisticsTop30VO copy = new DirectStatisticsTop30VO();
            copy.setMemberId(vo.getMemberId());
            copy.setMemberName(vo.getMemberName());
            copy.setMemberCode(vo.getMemberCode());
            copy.setNumberOfPeople(vo.getNumberOfPeople());
            copy.setNumberOfAmount(vo.getNumberOfAmount());
            copyList.add(copy);
        }
        return copyList;
    }

    /**
     * （用于测试）根据指定日期和时间粒度获取数据
     */
    public static List<DirectStatisticsTop30VO> getPreGeneratedDataByDate(
            int year, int month, int day, int hour, TimeGranularity granularity) {
        // 保存当前状态
        int originalSeed = currentSeed;
        TimeGranularity originalGranularity = currentGranularity;
        List<DirectStatisticsTop30VO> originalData = PERIODIC_PRE_GENERATED_DATA;

        try {
            // 设置指定日期的种子
            Calendar calendar = new GregorianCalendar(year, month - 1, day, hour, 0, 0);
            Date date = calendar.getTime();

            if (granularity == TimeGranularity.HOUR) {
                LocalDateTime localDateTime = date.toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime();
                currentSeed = Integer.parseInt(localDateTime.format(DateTimeFormatter.ofPattern("yyyyMMddHH")));
            } else {
                LocalDate localDate = date.toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate();
                currentSeed = Integer.parseInt(localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            }

            currentGranularity = granularity;

            // 重新生成指定日期的数据
            PERIODIC_PRE_GENERATED_DATA = generatePeriodicPredefinedData();

            // 返回生成的数据
            return getPeriodicPreGeneratedData(granularity);
        } finally {
            // 恢复原始状态
            currentSeed = originalSeed;
            currentGranularity = originalGranularity;
            PERIODIC_PRE_GENERATED_DATA = originalData;
        }
    }

    public static void main(String[] args) {
        // 按天生成数据
        List<DirectStatisticsTop30VO> dailyData = DataGeneratorUtils.generateFakeData(
                new ArrayList<>(), 30, 1, DataGeneratorUtils.TimeGranularity.DAY);
        System.out.println(JSONUtil.toJsonPrettyStr(dailyData));
        // 按小时生成数据
//        List<DirectStatisticsTop30VO> hourlyData = DataGeneratorUtils.generateFakeData(
//                new ArrayList<>(), 50, 2, DataGeneratorUtils.TimeGranularity.HOUR);
//        System.out.println(JSONUtil.toJsonPrettyStr(hourlyData));
    }
}
