package com.yaoai.ai.providers.service.impl;

import com.yaoai.ai.providers.service.SeedreamService;
import com.yaoai.common.exception.BizException;
import com.yaoai.common.exception.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.List;

@Slf4j
@Service
@Profile("dev-h2")
@ConditionalOnProperty(name = "ai.local-stub.enabled", havingValue = "true")
public class LocalSeedreamService implements SeedreamService {

    @Override
    public String generateImage(String prompt) {
        return generateImage(prompt, "2048x2048");
    }

    @Override
    public String generateImage(String prompt, String size) {
        return generateImage(prompt, size, List.of());
    }

    @Override
    public String generateImage(String prompt, String size, List<String> referenceImageUrls) {
        try {
            int[] wh = parseSize(size);
            String refNote = referenceImageUrls == null || referenceImageUrls.isEmpty()
                    ? ""
                    : "\nREFERENCE IMAGE MODE: " + referenceImageUrls.size() + " image(s)";
            byte[] bytes = renderPlaceholder((prompt == null ? "" : prompt) + refNote, wh[0], wh[1]);
            log.info("Local image stub generated: size={}, bytes={}", size, bytes.length);
            return "data:image/jpeg;base64," + Base64.getEncoder().encodeToString(bytes);
        } catch (Exception e) {
            throw new BizException(ErrorCode.INTERNAL_ERROR, "本地图片生成失败: " + e.getMessage());
        }
    }

    @Override
    public String getModelId() {
        return "local-dev-image";
    }

    @Override
    public String getModelName() {
        return "本地开发图片生成";
    }

    @Override
    public String getProvider() {
        return "local";
    }

    private int[] parseSize(String size) {
        if (size == null || !size.matches("\\d+x\\d+")) {
            return new int[] {1280, 720};
        }
        String[] parts = size.split("x");
        int width = Math.max(512, Math.min(2560, Integer.parseInt(parts[0])));
        int height = Math.max(512, Math.min(1440, Integer.parseInt(parts[1])));
        return new int[] {width, height};
    }

    private byte[] renderPlaceholder(String prompt, int width, int height) throws Exception {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        try {
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setColor(new Color(242, 246, 255));
            g.fillRect(0, 0, width, height);
            g.setColor(new Color(25, 55, 110));
            g.setStroke(new BasicStroke(Math.max(4f, width / 320f)));
            g.drawRoundRect(24, 24, width - 48, height - 48, 36, 36);

            boolean sheet = width > height;
            if (sheet) {
                drawCharacterSheet(g, width, height);
            } else {
                drawScenePlaceholder(g, width, height);
            }

            g.setColor(new Color(40, 55, 85));
            g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, Math.max(28, width / 48)));
            g.drawString(sheet ? "LOCAL CHARACTER SHEET" : "LOCAL SCENE IMAGE", 56, 78);

            g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, Math.max(18, width / 80)));
            drawWrapped(g, prompt == null ? "" : prompt, 56, height - 150, width - 112, Math.max(24, width / 68), 4);
        } finally {
            g.dispose();
        }

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", out);
        return out.toByteArray();
    }

    private void drawCharacterSheet(Graphics2D g, int width, int height) {
        String[] labels = {"head", "front", "side", "back"};
        int top = height / 5;
        int panelGap = width / 48;
        int panelWidth = (width - panelGap * 5) / 4;
        for (int i = 0; i < 4; i += 1) {
            int x = panelGap + i * (panelWidth + panelGap);
            g.setColor(Color.WHITE);
            g.fillRoundRect(x, top, panelWidth, height / 2, 28, 28);
            g.setColor(new Color(150, 165, 190));
            g.drawRoundRect(x, top, panelWidth, height / 2, 28, 28);
            g.setColor(new Color(82, 98, 135));
            int cx = x + panelWidth / 2;
            int cy = top + height / 5;
            int head = Math.max(36, panelWidth / 7);
            g.fillOval(cx - head, cy - head, head * 2, head * 2);
            g.setStroke(new BasicStroke(Math.max(6f, width / 180f)));
            g.drawLine(cx, cy + head, cx, top + height / 2 - 70);
            g.drawLine(cx, cy + head * 2, cx - panelWidth / 5, cy + height / 7);
            g.drawLine(cx, cy + head * 2, cx + panelWidth / 5, cy + height / 7);
            g.drawLine(cx, top + height / 2 - 70, cx - panelWidth / 6, top + height / 2 - 20);
            g.drawLine(cx, top + height / 2 - 70, cx + panelWidth / 6, top + height / 2 - 20);
            g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, Math.max(20, width / 90)));
            g.drawString(labels[i], x + 28, top + height / 2 - 24);
        }
    }

    private void drawScenePlaceholder(Graphics2D g, int width, int height) {
        g.setColor(Color.WHITE);
        g.fillRoundRect(width / 8, height / 5, width * 3 / 4, height / 2, 32, 32);
        g.setColor(new Color(105, 125, 170));
        g.setStroke(new BasicStroke(Math.max(5f, width / 220f)));
        g.drawLine(width / 6, height * 3 / 5, width * 5 / 6, height * 3 / 5);
        g.drawLine(width / 4, height * 3 / 5, width / 3, height / 3);
        g.drawLine(width / 3, height / 3, width / 2, height * 3 / 5);
        g.drawLine(width / 2, height * 3 / 5, width * 2 / 3, height / 3);
        g.drawLine(width * 2 / 3, height / 3, width * 3 / 4, height * 3 / 5);
    }

    private void drawWrapped(Graphics2D g, String text, int x, int y, int maxWidth, int lineHeight, int maxLines) {
        String[] words = text.replace('\n', ' ').split("\\s+");
        StringBuilder line = new StringBuilder();
        int lines = 0;
        for (String word : words) {
            String candidate = line.isEmpty() ? word : line + " " + word;
            if (g.getFontMetrics().stringWidth(candidate) > maxWidth && !line.isEmpty()) {
                g.drawString(line.toString(), x, y + lines * lineHeight);
                line = new StringBuilder(word);
                lines += 1;
                if (lines >= maxLines) return;
            } else {
                line = new StringBuilder(candidate);
            }
        }
        if (!line.isEmpty() && lines < maxLines) {
            g.drawString(line.toString(), x, y + lines * lineHeight);
        }
    }
}
