package cn.iocoder.yudao.module.server.service.policycommunications;

import cn.iocoder.yudao.module.server.controller.admin.policycommunications.vo.CaptchaImageRespDTO;
import cn.iocoder.yudao.module.system.framework.captcha.core.RedisCaptchaServiceImpl;
import com.anji.captcha.service.CaptchaCacheService;
import com.google.code.kaptcha.Producer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.Duration;
import java.util.Base64;
import java.util.UUID;

@Slf4j
@Service
public class TraditionalCaptchaMathService {

    @Resource(name = "mathCaptchaProducer")
    private Producer captchaProducer;

    @Resource
    private CaptchaCacheService redisService;

    // 验证码缓存前缀
    private static final String CAPTCHA_KEY = "policy:captcha:";
    // 验证码过期时间5分钟
    private static final Long CAPTCHA_EXPIRE = Duration.ofMinutes(5).toMillis();

    /**
     * 生成验证码图片
     */
    public CaptchaImageRespDTO generateCaptchaImage() {
        // 生成验证码文本（数学表达式，如 "3+4=?"）
        String captchaText = captchaProducer.createText();
        String uuid = UUID.randomUUID().toString();

        log.debug("生成数学验证码: {}, UUID: {}", captchaText, uuid);

        // 计算数学答案（如 "3+4=?" -> 7）
        int answer = calculateMathAnswer(captchaText);

        // 存储答案到Redis（不是原始表达式）
        String cacheKey = buildCaptchaKey(uuid);
        redisService.set(cacheKey, String.valueOf(answer), CAPTCHA_EXPIRE);

        // 生成图片
        BufferedImage image = captchaProducer.createImage(captchaText);

        CaptchaImageRespDTO respDTO = new CaptchaImageRespDTO();
        respDTO.setUuid(uuid);
        respDTO.setImg(convertImageToBase64(image));

        return respDTO;
    }

    /**
     * 计算数学表达式的答案
     */
    private int calculateMathAnswer(String expression) {
        try {
            // 去掉问号和等号，如 "3+4=?" -> "3+4"
            String mathExpr = expression.replace("=?", "").trim();

            // 处理加法
            if (mathExpr.contains("+")) {
                String[] parts = mathExpr.split("\\+");
                return Integer.parseInt(parts[0]) + Integer.parseInt(parts[1]);
            }

            // 处理减法
            if (mathExpr.contains("-")) {
                String[] parts = mathExpr.split("-");
                return Integer.parseInt(parts[0]) - Integer.parseInt(parts[1]);
            }

            // 处理乘法（×符号）
            if (mathExpr.contains("×")) {
                String[] parts = mathExpr.split("×");
                return Integer.parseInt(parts[0]) * Integer.parseInt(parts[1]);
            }

            log.error("无法识别的数学表达式: {}", expression);
            return 0;
        } catch (Exception e) {
            log.error("计算数学答案失败: {}", expression, e);
            return 0;
        }
    }

    /**
     * 验证验证码
     */
    public boolean verifyCaptcha(String uuid, String code) {
        if (uuid == null || code == null || code.trim().isEmpty()) {
            return false;
        }

        String cacheKey = buildCaptchaKey(uuid);
        String storedValue = redisService.get(cacheKey);

        if (storedValue == null) {
            log.warn("验证码已过期或不存在, UUID: {}", uuid);
            return false;
        }

        // 验证数学验证码
        boolean success = verifyMathCaptcha(code.trim(), storedValue);

        // 无论成功与否，都删除验证码（一次性使用）
        redisService.delete(cacheKey);

        if (!success) {
            log.warn("验证码验证失败, UUID: {}, 输入: {}, 正确答案: {}", uuid, code, storedValue);
        }

        return success;
    }

    /**
     * 验证数学验证码
     */
    private boolean verifyMathCaptcha(String userInput, String correctAnswer) {
        try {
            // 正确答案（已存储的数字）
            int correctValue = Integer.parseInt(correctAnswer);

            // 用户输入
            int userValue;

            // 如果用户输入的是纯数字
            if (userInput.matches("-?\\d+")) {
                userValue = Integer.parseInt(userInput);
            } else {
                // 用户可能输入了表达式，如 "3+4"
                userValue = evaluateMathExpression(userInput);
            }

            return userValue == correctValue;
        } catch (Exception e) {
            log.error("验证数学验证码失败, 用户输入: {}, 正确答案: {}", userInput, correctAnswer, e);
            return false;
        }
    }

    /**
     * 计算用户输入的数学表达式
     */
    private int evaluateMathExpression(String expression) {
        try {
            // 移除空格
            expression = expression.replaceAll("\\s+", "");

            // 处理加法
            if (expression.contains("+")) {
                String[] parts = expression.split("\\+");
                return Integer.parseInt(parts[0]) + Integer.parseInt(parts[1]);
            }

            // 处理减法
            if (expression.contains("-")) {
                String[] parts = expression.split("-");
                return Integer.parseInt(parts[0]) - Integer.parseInt(parts[1]);
            }

            // 处理乘法（支持×和*）
            if (expression.contains("×")) {
                String[] parts = expression.split("×");
                return Integer.parseInt(parts[0]) * Integer.parseInt(parts[1]);
            }
            if (expression.contains("*")) {
                String[] parts = expression.split("\\*");
                return Integer.parseInt(parts[0]) * Integer.parseInt(parts[1]);
            }

            // 如果都不是，尝试直接解析为数字
            return Integer.parseInt(expression);
        } catch (Exception e) {
            log.error("计算表达式失败: {}", expression, e);
            // 返回一个不可能的值，确保验证失败
            return Integer.MIN_VALUE;
        }
    }

    /**
     * 构建验证码缓存key
     */
    private String buildCaptchaKey(String uuid) {
        return CAPTCHA_KEY + uuid;
    }

    /**
     * 将BufferedImage转换为base64字符串
     */
    private String convertImageToBase64(BufferedImage image) {
        try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
            ImageIO.write(image, "jpg", os);
            String base64 = Base64.getEncoder().encodeToString(os.toByteArray());
            return "data:image/jpeg;base64," + base64;
        } catch (IOException e) {
            log.error("转换验证码图片失败", e);
            e.printStackTrace();
        }
        return null;
    }
}