package com.ylx.massage.utils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ylx.common.exception.ServiceException;
import com.ylx.massage.domain.TJs;
import com.ylx.massage.service.TJsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * 虚拟技师昵称生成器
 * <p>
 * 生成2-3个汉字的偏女性化昵称，确保全表唯一。
 * 使用常用姓氏和女性化名字组合，支持随机生成。
 * </p>
 *
 * @author ylx
 * @version 1.0
 * @since 2025-01-09
 */
@Slf4j
@Component
public class VirtualTechnicianNicknameGenerator {

    @Resource
    private TJsService tJsService;

    private static VirtualTechnicianNicknameGenerator instance;

    @PostConstruct
    public void init() {
        instance = this;
    }

    /**
     * 常用姓氏（前50个）
     */
    private static final String[] SURNAMES = {
            "王", "李", "张", "刘", "陈", "杨", "黄", "赵", "周", "吴",
            "徐", "孙", "马", "胡", "朱", "郭", "何", "罗", "高", "林",
            "梁", "郑", "谢", "宋", "唐", "许", "韩", "冯", "邓", "曹",
            "彭", "曾", "萧", "田", "董", "袁", "潘", "于", "蒋", "蔡",
            "余", "杜", "叶", "程", "苏", "魏", "吕", "丁", "任", "沈"
    };

    /**
     * 女性化常用字（用于名字）
     */
    private static final String[] FEMALE_CHARACTERS = {
            // 单字名（2字昵称：姓氏+单字）
            "婷", "雪", "慧", "颖", "雅", "静", "雯", "婷", "欣", "怡",
            "娜", "丹", "莉", "娟", "秀", "英", "华", "玉", "梅", "珍",
            "芳", "红", "敏", "霞", "丽", "桂", "琼", "琴", "兰", "平",
            "燕", "艳", "玲", "薇", "萍", "芬", "菊", "云", "莲", "珠",
            "文", "月", "凤", "宝", "金", "荣", "爱", "翠", "巧", "娴",

            // 双字名（3字昵称：姓氏+双字）
            // 第一字
            "小", "晓", "雨", "梦", "佳", "诗", "春", "夏", "秋", "冬",
            "紫", "子", "思", "嘉", "若", "如", "语", "妙", "玉", "可",

            // 第二字
            "萱", "璇", "瑶", "琪", "琳", "瑗", "瑛", "蓉", "蓓", "蕾",
            "薇", "蕊", "菲", "芳", "芸", "芝", "兰", "荷", "菊", "梅",
            "竹", "月", "雪", "云", "霞", "露", "霜", "冰", "清", "洁"
    };

    /**
     * 缓存已存在的昵称集合，避免频繁查询数据库
     */
    private Set<String> existingNicknames = null;

    /**
     * 生成唯一的虚拟技师昵称
     * <p>
     * 业务规则：
     * <ul>
     *   <li>生成长度为2-3个汉字的昵称</li>
     *   <li>偏女性化名字风格</li>
     *   <li>确保全表唯一（不与现有技师昵称重复）</li>
     *   <li>最多尝试1000次，避免无限循环</li>
     * </ul>
     * </p>
     *
     * @return 唯一的虚拟技师昵称
     * @throws ServiceException 当无法生成唯一昵称时抛出异常
     */
    public String generateUniqueNickname() {
        // 初始化已存在昵称缓存（懒加载）
        if (existingNicknames == null) {
            loadExistingNicknames();
        }

        // 最多尝试1000次
        int maxAttempts = 1000;
        for (int i = 0; i < maxAttempts; i++) {
            String nickname = generateRandomNickname();

            // 检查是否唯一
            if (!existingNicknames.contains(nickname)) {
                // 添加到缓存，防止本次批量操作中重复
                existingNicknames.add(nickname);
                log.debug("成功生成唯一昵称：{} (尝试次数：{})", nickname, i + 1);
                return nickname;
            }
        }

        throw new ServiceException("生成唯一昵称失败：已达到最大尝试次数(" + maxAttempts + ")，请稍后重试或联系管理员");
    }

    /**
     * 批量生成唯一的虚拟技师昵称
     *
     * @param count 需要生成的昵称数量
     * @return List<String> 昵称列表
     * @throws ServiceException 当无法生成足够数量的唯一昵称时抛出异常
     */
    public List<String> batchGenerateUniqueNicknames(int count) {
        if (count <= 0) {
            throw new ServiceException("生成数量必须大于0");
        }

        List<String> nicknames = new ArrayList<>(count);
        Set<String> generatedInThisBatch = new HashSet<>();

        // 初始化已存在昵称缓存
        if (existingNicknames == null) {
            loadExistingNicknames();
        }

        // 逐个生成昵称，确保不重复
        int maxAttempts = count * 100; // 每个昵称最多尝试100次
        int attempts = 0;

        while (generatedInThisBatch.size() < count && attempts < maxAttempts) {
            String nickname = generateRandomNickname();

            // 检查是否在数据库中已存在
            if (!existingNicknames.contains(nickname) && !generatedInThisBatch.contains(nickname)) {
                generatedInThisBatch.add(nickname);
                nicknames.add(nickname);
                // 添加到全局缓存
                existingNicknames.add(nickname);
            }

            attempts++;
        }

        if (nicknames.size() < count) {
            throw new ServiceException("批量生成昵称失败：期望生成" + count + "个，实际生成" + nicknames.size() + "个。请减少生成数量或联系管理员");
        }

        log.info("成功批量生成{}个唯一昵称", nicknames.size());
        return nicknames;
    }

    /**
     * 生成随机昵称（不保证唯一性）
     * <p>
     * 生成规则：
     * <ul>
     *   <li>50%概率生成2字昵称：姓氏 + 单字名</li>
     *   <li>50%概率生成3字昵称：姓氏 + 双字名</li>
     * </ul>
     * </p>
     *
     * @return String 随机生成的昵称
     */
    private String generateRandomNickname() {
        ThreadLocalRandom random = ThreadLocalRandom.current();

        // 随机选择姓氏
        String surname = SURNAMES[random.nextInt(SURNAMES.length)];

        // 50%概率生成2字昵称，50%概率生成3字昵称
        if (random.nextBoolean()) {
            // 2字昵称：姓氏 + 单字名
            String name = FEMALE_CHARACTERS[random.nextInt(50)]; // 使用前50个单字
            return surname + name;
        } else {
            // 3字昵称：姓氏 + 双字名
            String firstChar = FEMALE_CHARACTERS[50 + random.nextInt(20)]; // 第51-70个为第一字
            String secondChar = FEMALE_CHARACTERS[70 + random.nextInt(30)]; // 第71-100个为第二字
            return surname + firstChar + secondChar;
        }
    }

    /**
     * 从数据库加载所有已存在的昵称
     */
    private void loadExistingNicknames() {
        log.info("开始加载现有技师昵称数据...");
        try {
            // 查询所有技师的昵称
            LambdaQueryWrapper<TJs> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(TJs::getcNickName);
            queryWrapper.isNotNull(TJs::getcNickName);

            List<TJs> allJs = tJsService.list(queryWrapper);
            existingNicknames = allJs.stream()
                    .map(TJs::getcNickName)
                    .filter(Objects::nonNull)
                    .filter(nickname -> !nickname.trim().isEmpty())
                    .collect(Collectors.toSet());

            log.info("成功加载{}个现有技师昵称", existingNicknames.size());
        } catch (Exception e) {
            log.error("加载现有昵称数据失败", e);
            throw new ServiceException("加载现有昵称数据失败，请稍后重试");
        }
    }

    /**
     * 清空昵称缓存
     * <p>
     * 用于批量操作完成后清理缓存，释放内存。
     * </p>
     */
    public void clearCache() {
        if (existingNicknames != null) {
            existingNicknames.clear();
            existingNicknames = null;
            log.info("昵称缓存已清空");
        }
    }

    /**
     * 刷新昵称缓存
     * <p>
     * 重新从数据库加载最新昵称数据。
     * </p>
     */
    public void refreshCache() {
        clearCache();
        loadExistingNicknames();
        log.info("昵称缓存已刷新");
    }

    /**
     * 获取已缓存的昵称数量（用于监控）
     *
     * @return 缓存的昵称数量
     */
    public int getCachedNicknameCount() {
        return existingNicknames == null ? 0 : existingNicknames.size();
    }
}
