package com.stdproject.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Random;

/**
 * 验证码工具类
 *
 * @author StdProject
 */
@Component
@Slf4j
public class CaptchaUtils {

    /**
     * 验证码字符集
     */
    private static final String CAPTCHA_CHARS = "ABCDEFGHJKMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
    
    /**
     * 验证码长度
     */
    private static final int CAPTCHA_LENGTH = 4;
    
    /**
     * 图片宽度
     */
    private static final int IMAGE_WIDTH = 120;
    
    /**
     * 图片高度
     */
    private static final int IMAGE_HEIGHT = 40;
    
    /**
     * 干扰线数量
     */
    private static final int INTERFERENCE_LINE_COUNT = 5;
    
    /**
     * 干扰点数量
     */
    private static final int INTERFERENCE_POINT_COUNT = 50;

    /**
     * 验证码结果类
     */
    public static class CaptchaResult {
        private String code;
        private String imageBase64;
        
        public CaptchaResult(String code, String imageBase64) {
            this.code = code;
            this.imageBase64 = imageBase64;
        }
        
        public String getCode() {
            return code;
        }
        
        public String getImageBase64() {
            return imageBase64;
        }
    }

    /**
     * 生成验证码
     *
     * @return 验证码结果
     */
    public CaptchaResult generateCaptcha() {
        // 生成验证码字符串
        String code = generateRandomCode();
        
        // 生成验证码图片
        String imageBase64 = generateCaptchaImage(code);
        
        return new CaptchaResult(code, imageBase64);
    }

    /**
     * 生成随机验证码字符串
     *
     * @return 验证码字符串
     */
    private String generateRandomCode() {
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        
        for (int i = 0; i < CAPTCHA_LENGTH; i++) {
            int index = random.nextInt(CAPTCHA_CHARS.length());
            code.append(CAPTCHA_CHARS.charAt(index));
        }
        
        return code.toString();
    }

    /**
     * 生成验证码图片
     *
     * @param code 验证码字符串
     * @return Base64编码的图片
     */
    private String generateCaptchaImage(String code) {
        try {
            // 创建图片
            BufferedImage image = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();
            
            // 设置抗锯齿
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            
            // 填充背景
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
            
            // 绘制干扰线
            drawInterferenceLines(g2d);
            
            // 绘制验证码字符
            drawCaptchaText(g2d, code);
            
            // 绘制干扰点
            drawInterferencePoints(g2d);
            
            g2d.dispose();
            
            // 转换为Base64
            return imageToBase64(image);
            
        } catch (Exception e) {
            log.error("生成验证码图片失败: {}", e.getMessage(), e);
            return "";
        }
    }

    /**
     * 绘制干扰线
     *
     * @param g2d 图形对象
     */
    private void drawInterferenceLines(Graphics2D g2d) {
        Random random = new Random();
        
        for (int i = 0; i < INTERFERENCE_LINE_COUNT; i++) {
            int x1 = random.nextInt(IMAGE_WIDTH);
            int y1 = random.nextInt(IMAGE_HEIGHT);
            int x2 = random.nextInt(IMAGE_WIDTH);
            int y2 = random.nextInt(IMAGE_HEIGHT);
            
            g2d.setColor(getRandomColor(150, 200));
            g2d.setStroke(new BasicStroke(1.0f));
            g2d.drawLine(x1, y1, x2, y2);
        }
    }

    /**
     * 绘制验证码文字
     *
     * @param g2d 图形对象
     * @param code 验证码字符串
     */
    private void drawCaptchaText(Graphics2D g2d, String code) {
        Random random = new Random();
        int charWidth = IMAGE_WIDTH / CAPTCHA_LENGTH;
        
        for (int i = 0; i < code.length(); i++) {
            char c = code.charAt(i);
            
            // 随机字体大小
            int fontSize = 20 + random.nextInt(8);
            Font font = new Font("Arial", Font.BOLD, fontSize);
            g2d.setFont(font);
            
            // 随机颜色
            g2d.setColor(getRandomColor(20, 130));
            
            // 随机位置和角度
            int x = i * charWidth + random.nextInt(charWidth / 3) + 5;
            int y = IMAGE_HEIGHT / 2 + random.nextInt(10) - 5;
            
            // 随机旋转角度
            double angle = (random.nextDouble() - 0.5) * 0.4;
            g2d.rotate(angle, x, y);
            
            g2d.drawString(String.valueOf(c), x, y);
            
            // 恢复角度
            g2d.rotate(-angle, x, y);
        }
    }

    /**
     * 绘制干扰点
     *
     * @param g2d 图形对象
     */
    private void drawInterferencePoints(Graphics2D g2d) {
        Random random = new Random();
        
        for (int i = 0; i < INTERFERENCE_POINT_COUNT; i++) {
            int x = random.nextInt(IMAGE_WIDTH);
            int y = random.nextInt(IMAGE_HEIGHT);
            
            g2d.setColor(getRandomColor(100, 200));
            g2d.fillOval(x, y, 2, 2);
        }
    }

    /**
     * 获取随机颜色
     *
     * @param min 最小值
     * @param max 最大值
     * @return 随机颜色
     */
    private Color getRandomColor(int min, int max) {
        Random random = new Random();
        
        if (min > 255) min = 255;
        if (max > 255) max = 255;
        if (min < 0) min = 0;
        if (max < 0) max = 0;
        if (min > max) {
            int temp = min;
            min = max;
            max = temp;
        }
        
        int r = min + random.nextInt(max - min);
        int g = min + random.nextInt(max - min);
        int b = min + random.nextInt(max - min);
        
        return new Color(r, g, b);
    }

    /**
     * 图片转Base64
     *
     * @param image 图片
     * @return Base64字符串
     */
    private String imageToBase64(BufferedImage image) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", baos);
        byte[] imageBytes = baos.toByteArray();
        return "data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes);
    }

    /**
     * 验证验证码
     *
     * @param inputCode 用户输入的验证码
     * @param correctCode 正确的验证码
     * @return 是否验证通过
     */
    public boolean verifyCaptcha(String inputCode, String correctCode) {
        if (inputCode == null || correctCode == null) {
            return false;
        }
        return inputCode.equalsIgnoreCase(correctCode);
    }
}