/**
 * 一位数加法绘制服务
 */

import { BaseDrawService } from '../../../core/draw/baseDraw';
import { getRandomNumberColor } from '../../../constants/colors';

/**
 * 一位数加法数据
 */
export interface OneDigitAdditionData {
    problems: Array<{
        left: number;
        right: number;
        result: number;
    }>;
}

/**
 * 一位数加法绘制服务
 */
class OneDigitAdditionDraw extends BaseDrawService {
    additionData: OneDigitAdditionData | null = null;

    constructor(
        canvas: Canvas,
        ctx: RenderingContext,
        options?: Record<string, any>,
    ) {
        super(canvas, ctx, options);
        this.additionData = null;
    }

    /**
     * 绘制一位数加法内容
     */
    async draw(additionData: OneDigitAdditionData) {
        if (!additionData || !additionData.problems) {
            return;
        }

        this.additionData = additionData;
        this.prepareDraw();
        await this.drawHeaderAndDivider();
        await this.drawContent({
            canvas: this.canvas,
            ctx: this.ctx,
            problems: this.additionData.problems,
            canvasWidth: this.canvasWidth,
            startY: this.currentY,
        });
    }

    /**
     * 绘制内容区域
     */
    private async drawContent(params: {
        canvas: WechatMiniprogram.Canvas;
        ctx: RenderingContext;
        problems: Array<{
            left: number;
            right: number;
            result: number;
        }>;
        canvasWidth: number;
        startY: number;
    }): Promise<void> {
        const { ctx, problems, canvasWidth, startY } = params;
        const rowStartY = startY + 30; // 顶部间距
        const margin = 50;
        const rows = 6;
        const rowSpacing = 110; // 行间距

        // 计算可用宽度（单列居中）
        const availableWidth = canvasWidth - margin * 2;
        const colCenterX = canvasWidth / 2; // 列的中心点

        // 圆点相关参数（适度调大）
        const dotRadius = 5; // 圆点半径（调大）
        const dotSpacing = 8; // 圆点之间的间距（调大）
        const dotsPerRow = 5; // 每行最多5个圆点
        const dotRowSpacing = 8; // 圆点行之间的间距（调大）

        // 数字和符号相关参数
        const fontSize = 26;
        const numberSpacing = 14; // 数字之间的间距
        const boxSize = 36; // 答案框大小
        const boxBorderColor = '#555'; // 答案框边框颜色

        // 计算每道题的起始位置（6行1列）
        for (let row = 0; row < rows; row++) {
            const problemIndex = row;
            if (problemIndex >= problems.length) {
                break;
            }

            const problem = problems[problemIndex];
            const problemY = rowStartY + row * rowSpacing;

            // 绘制单道题（在页面中居中）
            this.drawSingleProblem(
                ctx,
                colCenterX - availableWidth / 2, // 列的起始X坐标
                problemY,
                availableWidth, // 使用可用宽度
                problem,
                {
                    dotRadius,
                    dotSpacing,
                    dotsPerRow,
                    dotRowSpacing,
                    fontSize,
                    numberSpacing,
                    boxSize,
                    boxBorderColor,
                },
            );

            // 绘制行之间的虚线分割（除了最后一行）
            if (row < rows - 1) {
                const dividerY = rowStartY + (row + 1) * rowSpacing - 20;
                this.drawDashedDivider(dividerY, margin);
            }
        }
    }

    /**
     * 绘制单道题
     */
    private drawSingleProblem(
        ctx: RenderingContext,
        x: number,
        y: number,
        width: number,
        problem: { left: number; right: number; result: number },
        options: {
            dotRadius: number;
            dotSpacing: number;
            dotsPerRow: number;
            dotRowSpacing: number;
            fontSize: number;
            numberSpacing: number;
            boxSize: number;
            boxBorderColor: string;
        },
    ) {
        const {
            dotRadius,
            dotSpacing,
            dotsPerRow,
            dotRowSpacing,
            fontSize,
            numberSpacing,
            boxSize,
            boxBorderColor,
        } = options;

        // 为整个运算公式生成统一的随机颜色
        const problemColor = getRandomNumberColor();

        // 计算5个圆点的最大宽度（统一使用，确保间距一致）
        const maxDotsWidth = this.calculateDotsWidth(
            dotsPerRow, // 使用5个圆点的宽度
            dotsPerRow,
            dotRadius,
            dotSpacing,
        );

        // 计算每个元素的宽度（统一使用5个圆点的宽度）
        const leftElementWidth = Math.max(maxDotsWidth, fontSize);
        const rightElementWidth = Math.max(maxDotsWidth, fontSize);
        const resultElementWidth = Math.max(maxDotsWidth, boxSize);

        // 计算总宽度并居中
        const symbolWidth = 24; // 符号宽度（缩小）
        const totalWidth =
            leftElementWidth +
            numberSpacing +
            symbolWidth + // 加号宽度
            numberSpacing +
            rightElementWidth +
            numberSpacing +
            symbolWidth + // 等号宽度
            numberSpacing +
            resultElementWidth;

        const startX = x + (width - totalWidth) / 2;
        let currentX = startX;

        // 计算统一的圆点区域高度（始终使用两行的高度，保持每行高度一致）
        const dotsAreaHeight = 2 * dotRadius * 2 + dotRowSpacing; // 2行的高度
        // 圆点区域的底部Y坐标（所有圆点都从底部开始绘制）
        const dotsBottomY = y + dotsAreaHeight;
        // 数字/方框的Y坐标（下方，与圆点底部对齐）
        const resultBoxY = dotsBottomY + 12;
        const numberY = resultBoxY + (boxSize - fontSize) / 2 + 2;

        // 绘制左侧圆点和数字
        const leftCenterX = currentX + leftElementWidth / 2;
        const leftDotsWidth = this.calculateDotsWidth(
            problem.left,
            dotsPerRow,
            dotRadius,
            dotSpacing,
        );
        this.drawDots(
            ctx,
            leftCenterX - leftDotsWidth / 2,
            dotsBottomY, // 从底部开始绘制
            problem.left,
            problemColor,
            dotRadius,
            dotSpacing,
            dotsPerRow,
            dotRowSpacing,
        );
        ctx.fillStyle = '#000';
        ctx.font = `bold ${fontSize}px Arial`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'top';
        ctx.fillText(String(problem.left), leftCenterX, numberY);

        currentX += leftElementWidth + numberSpacing;

        // 绘制加号（与数字垂直居中对齐）
        const plusX = currentX + symbolWidth / 2;
        const plusY = numberY + fontSize / 2;
        this.drawSymbol(plusX, plusY, '+', symbolWidth * 0.8);
        currentX = plusX + symbolWidth / 2 + numberSpacing;

        // 绘制右侧圆点和数字
        const rightCenterX = currentX + rightElementWidth / 2;
        const rightDotsWidth = this.calculateDotsWidth(
            problem.right,
            dotsPerRow,
            dotRadius,
            dotSpacing,
        );
        this.drawDots(
            ctx,
            rightCenterX - rightDotsWidth / 2,
            dotsBottomY, // 从底部开始绘制
            problem.right,
            problemColor,
            dotRadius,
            dotSpacing,
            dotsPerRow,
            dotRowSpacing,
        );
        ctx.fillStyle = '#000';
        ctx.fillText(String(problem.right), rightCenterX, numberY);

        currentX += rightElementWidth + numberSpacing;

        // 绘制等号（与数字垂直居中对齐）
        const equalsX = currentX + symbolWidth / 2;
        const equalsY = numberY + fontSize / 2;
        this.drawSymbol(equalsX, equalsY, '=', symbolWidth * 0.8);
        currentX = equalsX + symbolWidth / 2 + numberSpacing;

        // 绘制结果圆点和答案框
        const resultCenterX = currentX + resultElementWidth / 2;
        const resultDotsWidth = this.calculateDotsWidth(
            problem.result,
            dotsPerRow,
            dotRadius,
            dotSpacing,
        );
        this.drawDots(
            ctx,
            resultCenterX - resultDotsWidth / 2,
            dotsBottomY, // 从底部开始绘制
            problem.result,
            problemColor,
            dotRadius,
            dotSpacing,
            dotsPerRow,
            dotRowSpacing,
        );

        // 绘制答案框（与数字垂直对齐）
        const resultBoxX = resultCenterX - boxSize / 2;
        this.drawRoundedRect(resultBoxX, resultBoxY, boxSize, boxSize, {
            isDashed: false,
            radius: 4,
            color: boxBorderColor,
            lineWidth: 1,
        });
    }

    /**
     * 绘制圆点
     * y 参数是圆点区域的底部Y坐标
     * 先绘制下面一行（满5个后），再绘制上面一行
     */
    private drawDots(
        ctx: RenderingContext,
        x: number,
        y: number, // 圆点区域的底部Y坐标
        count: number,
        color: string,
        radius: number,
        spacing: number,
        dotsPerRow: number,
        rowSpacing: number,
    ) {
        for (let i = 0; i < count; i++) {
            let row: number;
            let col: number;

            if (count <= dotsPerRow) {
                // 只有一行，在底部（row = 0 表示最下面一行）
                row = 0;
                col = i;
            } else {
                // 多行情况：先绘制下面一行（前5个），再绘制上面一行（剩余的）
                if (i < dotsPerRow) {
                    // 下面一行（row = 0 表示最下面一行）
                    row = 0;
                    col = i;
                } else {
                    // 上面一行（row = 1 表示上面一行）
                    row = 1;
                    col = i - dotsPerRow;
                }
            }

            // 从底部向上计算Y坐标
            // row = 0 时在最下面，row = 1 时在上面
            const dotX = x + col * (radius * 2 + spacing);
            const dotY = y - (row * (radius * 2 + rowSpacing) + radius * 2);

            this.drawDot(ctx, dotX + radius, dotY + radius, radius, color);
        }
    }

    /**
     * 计算圆点区域的宽度
     */
    private calculateDotsWidth(
        count: number,
        dotsPerRow: number,
        radius: number,
        spacing: number,
    ): number {
        const actualCols = Math.min(count, dotsPerRow);
        if (actualCols === 0) return 0;
        return actualCols * radius * 2 + (actualCols - 1) * spacing;
    }

    /**
     * 计算圆点区域的高度
     */
    private calculateDotsHeight(
        count: number,
        dotsPerRow: number,
        radius: number,
        rowSpacing: number,
    ): number {
        const rows = Math.ceil(count / dotsPerRow);
        if (rows === 0) return 0;
        return rows * radius * 2 + (rows - 1) * rowSpacing;
    }
}

export default OneDigitAdditionDraw;
