import { BaseDrawService } from '../../../core/draw/baseDraw';
import type {
    LetterTracingData,
    TracingRow,
} from '../../../core/generators/letter-tracing-generator';

const M = 24;
const BLUE = '#4A90E2';
const ORANGE = '#FF8C42';

/**
 * 字母描红绘制（tracing-writing + letter-tracing 的客户端实现）
 */
export default class LetterTracingDraw extends BaseDrawService {
    constructor(
        canvas: Canvas,
        ctx: RenderingContext,
        options?: Record<string, unknown>,
    ) {
        super(canvas, ctx, options);
    }

    async draw(data: LetterTracingData) {
        this.prepareDraw();
        await this.drawHeaderAndDivider();

        switch (data.mode) {
            case 'single-letter':
                this.drawSingleLetter(data);
                break;
            case 'full-alphabet':
                this.drawFullAlphabet(data.rows);
                break;
            case 'upper-lower-split':
                this.drawUpperLowerSplit(data.upperGlyphs, data.lowerGlyphs);
                break;
            case 'two-column':
                this.drawTwoColumn(data.leftRows, data.rightRows);
                break;
        }
    }

    /** 四线三格：顶线、中虚线、基线、底线 */
    private drawFourLines(x: number, y: number, w: number, h: number) {
        const ctx = this.ctx;
        const yTop = y;
        const yMid = y + h * 0.28;
        const yBase = y + h * 0.62;
        const yBot = y + h;

        ctx.strokeStyle = BLUE;
        ctx.lineWidth = 1;
        ctx.setLineDash([]);
        ctx.beginPath();
        ctx.moveTo(x, yTop);
        ctx.lineTo(x + w, yTop);
        ctx.stroke();

        ctx.strokeStyle = ORANGE;
        ctx.setLineDash([6, 6]);
        ctx.beginPath();
        ctx.moveTo(x, yMid);
        ctx.lineTo(x + w, yMid);
        ctx.stroke();

        ctx.strokeStyle = BLUE;
        ctx.setLineDash([]);
        ctx.lineWidth = 1.2;
        ctx.beginPath();
        ctx.moveTo(x, yBase);
        ctx.lineTo(x + w, yBase);
        ctx.stroke();

        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(x, yBot);
        ctx.lineTo(x + w, yBot);
        ctx.stroke();
    }

    private drawCharInCell(
        ch: string,
        x: number,
        y: number,
        w: number,
        h: number,
        opacity: number,
        bold: boolean,
    ) {
        const ctx = this.ctx;
        if (opacity <= 0) return;
        const fontSize = Math.min(h * 0.72, w * 0.85);
        ctx.save();
        ctx.globalAlpha = opacity;
        ctx.fillStyle = bold ? '#111' : '#666';
        ctx.font = `${bold ? 'bold ' : ''}${fontSize}px sans-serif`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'alphabetic';
        const baselineY = y + h * 0.62;
        ctx.fillText(ch, x + w / 2, baselineY);
        ctx.restore();
    }

    private drawTracingRow(
        row: TracingRow,
        startX: number,
        y: number,
        rowH: number,
        totalWidth: number,
    ) {
        const gap = 4;
        const n = row.cells.length;
        const cellW = (totalWidth - gap * (n - 1)) / n;

        for (let i = 0; i < n; i++) {
            const cx = startX + i * (cellW + gap);
            this.drawFourLines(cx, y, cellW, rowH);
            const cell = row.cells[i];
            this.drawCharInCell(
                cell.char,
                cx,
                y,
                cellW,
                rowH,
                cell.opacity,
                cell.isGuide,
            );
        }
    }

    private drawSingleLetter(
        data: Extract<LetterTracingData, { mode: 'single-letter' }>,
    ) {
        const ctx = this.ctx;
        const { teaching, rows } = data;
        const cw = this.canvasWidth;
        let y = this.currentY + 8;
        const teachH = Math.min(220, (this.canvasHeight - y) * 0.42);

        // 教学区背景
        ctx.fillStyle = '#f8fafc';
        ctx.fillRect(M, y, cw - M * 2, teachH);

        // 左侧 emoji
        ctx.font = `${Math.min(88, teachH * 0.45)}px sans-serif`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText(teaching.emoji, M + (cw - M * 2) * 0.22, y + teachH / 2);

        // 右侧文字
        const tx = M + (cw - M * 2) * 0.42;
        ctx.textAlign = 'left';
        ctx.textBaseline = 'top';
        ctx.fillStyle = '#111';
        ctx.font = 'bold 44px sans-serif';
        ctx.fillText(`${teaching.upper}  ${teaching.lower}`, tx, y + 16);
        ctx.font = '22px sans-serif';
        ctx.fillStyle = '#333';
        ctx.fillText(teaching.sentence, tx, y + 72);
        ctx.fillStyle = '#666';
        ctx.font = '18px sans-serif';
        ctx.fillText(teaching.word, tx, y + 104);

        y += teachH + 12;
        this.drawDashedDivider(y, M, '#ccc');
        y += 14;

        const rest = this.canvasHeight - y - M;
        const rowH = Math.max(36, (rest - 8) / rows.length);
        const rowWidth = cw - M * 2;
        for (let r = 0; r < rows.length; r++) {
            this.drawTracingRow(
                rows[r],
                M,
                y + r * (rowH + 10),
                rowH,
                rowWidth,
            );
        }
    }

    private drawFullAlphabet(rows: TracingRow[]) {
        const y0 = this.currentY + 6;
        const bottom = this.canvasHeight - M;
        const totalH = bottom - y0;
        const rowH = Math.max(14, totalH / rows.length - 2);
        const rowWidth = this.canvasWidth - M * 2;

        for (let i = 0; i < rows.length; i++) {
            const y = y0 + i * (rowH + 2);
            this.drawTracingRow(rows[i], M, y, rowH, rowWidth);
        }
    }

    private drawUpperLowerSplit(upper: string[], lower: string[]) {
        const ctx = this.ctx;
        const cw = this.canvasWidth;
        let y = this.currentY + 6;
        const innerW = cw - M * 2;

        const drawBlockTitle = (t: string) => {
            ctx.fillStyle = '#111';
            ctx.font = 'bold 18px sans-serif';
            ctx.textAlign = 'left';
            ctx.textBaseline = 'top';
            ctx.fillText(t, M, y);
            y += 26;
        };

        const drawGlyphGrid = (chars: string[], cols: number) => {
            const rows = Math.ceil(chars.length / cols);
            const cellW = (innerW - (cols - 1) * 4) / cols;
            const cellH = 32;

            for (let r = 0; r < rows; r++) {
                for (let c = 0; c < cols; c++) {
                    const idx = r * cols + c;
                    if (idx >= chars.length) break;
                    const cx = M + c * (cellW + 4);
                    this.drawFourLines(cx, y, cellW, cellH);
                    this.drawCharInCell(
                        chars[idx],
                        cx,
                        y,
                        cellW,
                        cellH,
                        0.85,
                        true,
                    );
                }
                y += cellH + 6;
            }
        };

        drawBlockTitle('大写字母 Uppercase');
        drawGlyphGrid(upper, 13);
        y += 8;
        this.drawDashedDivider(y, M, '#bbb');
        y += 14;
        drawBlockTitle('小写字母 Lowercase');
        drawGlyphGrid(lower, 13);
    }

    private drawTwoColumn(leftRows: TracingRow[], rightRows: TracingRow[]) {
        const y0 = this.currentY + 6;
        const bottom = this.canvasHeight - M;
        const totalH = bottom - y0;
        const maxRows = Math.max(leftRows.length, rightRows.length);
        const rowH = Math.max(16, totalH / maxRows - 3);
        const gapCol = 16;
        const colW = (this.canvasWidth - M * 2 - gapCol) / 2;

        for (let i = 0; i < leftRows.length; i++) {
            const y = y0 + i * (rowH + 3);
            this.drawTracingRow(leftRows[i], M, y, rowH, colW);
        }
        const xR = M + colW + gapCol;
        for (let i = 0; i < rightRows.length; i++) {
            const y = y0 + i * (rowH + 3);
            this.drawTracingRow(rightRows[i], xR, y, rowH, colW);
        }
    }
}
