/**
 * 加减法计算绘制服务
 */

import { BaseDrawService } from '../../../core/draw/baseDraw';
import { getImage } from '../../../utils/index';

/**
 * 加减法计算数据
 */
export interface AdditionData {
    problems: Array<{
        type: 'addition' | 'subtraction';
        left: number;
        right: number;
        result: number;
    }>;
}

/**
 * 加减法计算绘制服务
 */
class AdditionDraw extends BaseDrawService {
    calculationData: AdditionData | null = null;

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

    /**
     * 绘制加减法计算内容
     */
    async draw(
        calculationData: AdditionData,
        _calculationType: string = 'addition-5', // 保留参数以保持接口兼容性
        _imageType?: string, // 可选，不再使用，每个运算会随机选择图片类型
    ) {
        if (!calculationData || !calculationData.problems) {
            return;
        }

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

    /**
     * 绘制内容区域
     */
    private async drawContent(params: {
        canvas: WechatMiniprogram.Canvas;
        ctx: RenderingContext;
        problems: Array<{
            type: 'addition' | 'subtraction';
            left: number;
            right: number;
            result: number;
        }>;
        canvasWidth: number;
        startY: number;
    }): Promise<void> {
        const { canvas, ctx, problems, canvasWidth, startY } = params;

        // 根据图片类型确定图片目录和最大索引
        const imageConfig = {
            'twelve-animals': {
                folder: 'twelve-animals',
                maxIndex: 12,
            },
            fruits: {
                folder: 'fruits',
                maxIndex: 22,
            },
        };

        const leftMargin = 24;
        const rightMargin = 24;
        const itemSpacing = 140;
        // 调整左右框宽度比例：6:4 (约420:280)
        const leftBoxWidth = 334; // 左侧图片框固定宽度
        const rightBoxWidth = 196; // 右侧答案框固定宽度
        const boxHeight = 110;
        const borderRadius = 12;

        const imageSpacing = 0; // 图片之间的间距（水平方向）
        const rowSpacing = 4; // 第一行和第二行之间的间距（垂直方向）
        const padding = 15; // 框内边距
        const startYPos = startY + 20;
        const plusSignSize = 20; // 加号大小（缩小）
        const plusSignSpacing = 15; // 加号左右间距（方便修改和调试）

        // 计算左侧和右侧的起始X位置
        const leftBoxX = leftMargin;
        const rightBoxX = canvasWidth - rightMargin - rightBoxWidth;

        // 为每个题目随机选择图片类型和图片索引
        const problemImageConfigs: Array<{
            type: 'twelve-animals' | 'fruits';
            imageIndex: number;
        }> = [];

        for (let i = 0; i < problems.length; i++) {
            // 随机选择图片类型
            const imageTypes: ('twelve-animals' | 'fruits')[] = [
                'twelve-animals',
                'fruits',
            ];
            const randomType =
                imageTypes[Math.floor(Math.random() * imageTypes.length)];
            const config = imageConfig[randomType];

            // 为当前题目生成唯一的图片索引
            const availableImageIndices = Array.from(
                { length: config.maxIndex },
                (_, i) => i + 1,
            );
            const randomIndex = Math.floor(
                Math.random() * availableImageIndices.length,
            );
            const imageIndex = availableImageIndices[randomIndex];

            problemImageConfigs.push({
                type: randomType,
                imageIndex,
            });
        }

        // 绘制每一行的内容
        for (let i = 0; i < problems.length; i++) {
            const problem = problems[i];
            const boxY = startYPos + i * itemSpacing;
            const imageConfigItem = problemImageConfigs[i];
            const config = imageConfig[imageConfigItem.type];

            // 根据图片类型获取图片大小
            const imageSize = this.getImageSize(imageConfigItem.type);

            // 加载图片
            let image: any = null;
            try {
                const imagePath = `/mathPages/shared/assets/${config.folder}/${imageConfigItem.imageIndex}.png`;
                image = await getImage(canvas, imagePath);
            } catch (error) {
                console.error('图片加载失败:', error);
            }

            // ========== 绘制左侧图片框 ==========
            ctx.strokeStyle = '#999';
            ctx.lineWidth = 1;
            this.drawRoundedRectInternal(
                ctx,
                leftBoxX,
                boxY,
                leftBoxWidth,
                boxHeight,
                borderRadius,
                true,
            );

            const leftBoxCenterY = boxY + boxHeight / 2;
            const leftBoxContentX = leftBoxX + padding;

            if (problem.type === 'addition') {
                // 加法：左侧图片 + 加号 + 右侧图片
                const leftImageCount = problem.left;
                const rightImageCount = problem.right;

                /**
                 * 根据数量计算每行最多展示的图片数
                 */
                const getMaxImagesPerRow = (count: number): number => {
                    if (count <= 6) return 3;
                    if (count <= 8) return 4;
                    return 5; // 8-10
                };

                const leftMaxPerRow = getMaxImagesPerRow(leftImageCount);
                const rightMaxPerRow = getMaxImagesPerRow(rightImageCount);
                const leftRows = Math.min(
                    2,
                    Math.ceil(leftImageCount / leftMaxPerRow),
                );
                const rightRows = Math.min(
                    2,
                    Math.ceil(rightImageCount / rightMaxPerRow),
                );

                // 计算左侧图片区域的宽度和高度
                // 需要根据实际行数计算每行的最大宽度
                const leftFirstRowCount = Math.min(
                    leftImageCount,
                    leftMaxPerRow,
                );
                const leftSecondRowCount = Math.max(
                    0,
                    Math.min(leftMaxPerRow, leftImageCount - leftMaxPerRow),
                );
                const leftImagesWidth =
                    Math.max(
                        leftFirstRowCount * imageSize +
                            (leftFirstRowCount - 1) * imageSpacing,
                        leftSecondRowCount * imageSize +
                            (leftSecondRowCount - 1) * imageSpacing,
                    ) || imageSize; // 至少为 imageSize

                // 计算右侧图片区域的宽度和高度
                const rightFirstRowCount = Math.min(
                    rightImageCount,
                    rightMaxPerRow,
                );
                const rightSecondRowCount = Math.max(
                    0,
                    Math.min(rightMaxPerRow, rightImageCount - rightMaxPerRow),
                );
                const rightImagesWidth =
                    Math.max(
                        rightFirstRowCount * imageSize +
                            (rightFirstRowCount - 1) * imageSpacing,
                        rightSecondRowCount * imageSize +
                            (rightSecondRowCount - 1) * imageSpacing,
                    ) || imageSize; // 至少为 imageSize

                // 获取图片实际高度（用于垂直居中计算）
                let imageActualHeight = imageSize;
                if (image) {
                    // @ts-ignore
                    imageActualHeight =
                        (image.height / image.width) * imageSize;
                }

                // 计算左侧图片区域的实际高度（考虑图片的实际高度和行间距）
                const leftImagesHeight =
                    leftRows * imageActualHeight + (leftRows - 1) * rowSpacing;
                // 计算右侧图片区域的实际高度
                const rightImagesHeight =
                    rightRows * imageActualHeight +
                    (rightRows - 1) * rowSpacing;

                // 计算加号位置（居中，包含左右间距）
                const totalContentWidth =
                    leftImagesWidth +
                    plusSignSpacing +
                    plusSignSize +
                    plusSignSpacing +
                    rightImagesWidth;
                const availableWidth = leftBoxWidth - padding * 2;
                const contentStartX =
                    leftBoxContentX + (availableWidth - totalContentWidth) / 2;

                const leftImagesStartX = contentStartX;
                // 垂直居中：使用图片实际高度计算
                const leftImagesStartY = leftBoxCenterY - leftImagesHeight / 2;

                // 绘制左侧图片（最多两行）
                for (let j = 0; j < Math.min(leftImageCount, 10); j++) {
                    const row = Math.floor(j / leftMaxPerRow);
                    const col = j % leftMaxPerRow;

                    // 如果超过两行，停止绘制
                    if (row >= 2) break;

                    const imagesInThisRow = Math.min(
                        leftMaxPerRow,
                        leftImageCount - row * leftMaxPerRow,
                    );
                    const rowWidth =
                        imagesInThisRow * imageSize +
                        (imagesInThisRow - 1) * imageSpacing;
                    const rowStartX =
                        leftImagesStartX + (leftImagesWidth - rowWidth) / 2;

                    const imageX = rowStartX + col * (imageSize + imageSpacing);
                    // 使用图片实际高度和行间距计算垂直位置
                    const imageY =
                        leftImagesStartY +
                        row * (imageActualHeight + rowSpacing);

                    if (image) {
                        // @ts-ignore
                        const scaledHeight =
                            (image.height / image.width) * imageSize;
                        ctx.drawImage(
                            image,
                            imageX,
                            imageY,
                            imageSize,
                            scaledHeight,
                        );
                    }
                }

                // 绘制加号（左右有间距）
                const plusX =
                    leftImagesStartX +
                    leftImagesWidth +
                    plusSignSpacing +
                    plusSignSize / 2;
                const plusY = leftBoxCenterY;
                ctx.strokeStyle = '#000';
                ctx.lineWidth = 2;
                ctx.beginPath();
                // 横线
                ctx.moveTo(plusX - plusSignSize / 2, plusY);
                ctx.lineTo(plusX + plusSignSize / 2, plusY);
                // 竖线
                ctx.moveTo(plusX, plusY - plusSignSize / 2);
                ctx.lineTo(plusX, plusY + plusSignSize / 2);
                ctx.stroke();

                const rightImagesStartX =
                    plusX + plusSignSize / 2 + plusSignSpacing;
                // 垂直居中：使用图片实际高度计算
                const rightImagesStartY =
                    leftBoxCenterY - rightImagesHeight / 2;

                // 绘制右侧图片（最多两行）
                for (let j = 0; j < Math.min(rightImageCount, 10); j++) {
                    const row = Math.floor(j / rightMaxPerRow);
                    const col = j % rightMaxPerRow;

                    // 如果超过两行，停止绘制
                    if (row >= 2) break;

                    const imagesInThisRow = Math.min(
                        rightMaxPerRow,
                        rightImageCount - row * rightMaxPerRow,
                    );
                    const rowWidth =
                        imagesInThisRow * imageSize +
                        (imagesInThisRow - 1) * imageSpacing;
                    const rowStartX =
                        rightImagesStartX + (rightImagesWidth - rowWidth) / 2;

                    const imageX = rowStartX + col * (imageSize + imageSpacing);
                    // 使用图片实际高度和行间距计算垂直位置
                    const imageY =
                        rightImagesStartY +
                        row * (imageActualHeight + rowSpacing);

                    if (image) {
                        // @ts-ignore
                        const scaledHeight =
                            (image.height / image.width) * imageSize;
                        ctx.drawImage(
                            image,
                            imageX,
                            imageY,
                            imageSize,
                            scaledHeight,
                        );
                    }
                }
            } else {
                // 减法：展示总数量的图片，后几个加划线
                const totalCount = problem.left; // 总数
                const subtractCount = problem.right; // 要减去的数量

                // 获取图片实际高度（用于垂直居中计算）
                let imageActualHeight = imageSize;
                if (image) {
                    // @ts-ignore
                    imageActualHeight =
                        (image.height / image.width) * imageSize;
                }

                // 计算图片布局
                const imagesPerRow = 5;
                const totalRows = Math.ceil(totalCount / imagesPerRow);
                // 使用图片实际高度和行间距计算总高度
                const totalHeight =
                    totalRows * imageActualHeight +
                    (totalRows - 1) * rowSpacing;
                const imagesStartY = leftBoxCenterY - totalHeight / 2;

                // 绘制所有图片
                for (let j = 0; j < totalCount; j++) {
                    const row = Math.floor(j / imagesPerRow);
                    const col = j % imagesPerRow;
                    const imagesInThisRow = Math.min(
                        imagesPerRow,
                        totalCount - row * imagesPerRow,
                    );
                    const rowWidth =
                        imagesInThisRow * imageSize +
                        (imagesInThisRow - 1) * imageSpacing;
                    const rowStartX =
                        leftBoxContentX +
                        (leftBoxWidth - padding * 2 - rowWidth) / 2;

                    const imageX = rowStartX + col * (imageSize + imageSpacing);
                    // 使用图片实际高度和行间距计算垂直位置
                    const imageY =
                        imagesStartY + row * (imageActualHeight + rowSpacing);

                    if (image) {
                        // @ts-ignore
                        const scaledHeight =
                            (image.height / image.width) * imageSize;
                        ctx.drawImage(
                            image,
                            imageX,
                            imageY,
                            imageSize,
                            scaledHeight,
                        );

                        // 如果是后几个图片，绘制虚线删除线（表示减去）
                        if (j >= totalCount - subtractCount) {
                            ctx.strokeStyle = '#000';
                            ctx.lineWidth = 2;
                            ctx.setLineDash([4, 3]); // 设置虚线样式
                            ctx.beginPath();
                            // 绘制第一条虚线对角线（从左上到右下）
                            ctx.moveTo(imageX, imageY);
                            ctx.lineTo(
                                imageX + imageSize,
                                imageY + scaledHeight,
                            );
                            ctx.stroke();
                            ctx.setLineDash([]); // 重置为实线，防止影响后续绘制
                        }
                    }
                }
            }

            // ========== 绘制右侧答案框 ==========
            this.drawAnswerBoxArea(ctx, {
                rightBoxX,
                boxY,
                rightBoxWidth,
                borderRadius,
                boxHeight,
                padding,
                problemType: problem.type,
            });
        }
    }

    /**
     * 绘制圆角矩形（虚线或实线边框）
     */
    private drawRoundedRectInternal(
        ctx: RenderingContext,
        x: number,
        y: number,
        width: number,
        height: number,
        radius: number,
        isDashed: boolean = true,
    ) {
        ctx.beginPath();
        ctx.moveTo(x + radius, y);
        ctx.lineTo(x + width - radius, y);
        ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
        ctx.lineTo(x + width, y + height - radius);
        ctx.quadraticCurveTo(
            x + width,
            y + height,
            x + width - radius,
            y + height,
        );
        ctx.lineTo(x + radius, y + height);
        ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
        ctx.lineTo(x, y + radius);
        ctx.quadraticCurveTo(x, y, x + radius, y);
        ctx.closePath();

        if (isDashed) {
            ctx.setLineDash([2, 2]); // 虚线
        } else {
            ctx.setLineDash([]); // 实线
        }
        ctx.stroke();
        ctx.setLineDash([]); // 重置为实线
    }

    /**
     * 绘制实线圆角方框（用于填写答案）
     */
    private drawAnswerBox(
        ctx: RenderingContext,
        x: number,
        y: number,
        width: number,
        height: number,
    ) {
        const radius = 6; // 圆角大小
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 1;
        ctx.setLineDash([]); // 实线
        ctx.beginPath();
        ctx.moveTo(x + radius, y);
        ctx.lineTo(x + width - radius, y);
        ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
        ctx.lineTo(x + width, y + height - radius);
        ctx.quadraticCurveTo(
            x + width,
            y + height,
            x + width - radius,
            y + height,
        );
        ctx.lineTo(x + radius, y + height);
        ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
        ctx.lineTo(x, y + radius);
        ctx.quadraticCurveTo(x, y, x + radius, y);
        ctx.closePath();
        ctx.stroke();
    }

    /**
     * 绘制右侧答案框
     */
    private drawAnswerBoxArea(
        ctx: RenderingContext,
        params: {
            rightBoxX: number;
            boxY: number;
            rightBoxWidth: number;
            borderRadius: number;
            boxHeight: number;
            padding: number;
            problemType: 'addition' | 'subtraction';
        },
    ) {
        const {
            rightBoxX,
            boxY,
            rightBoxWidth,
            borderRadius,
            boxHeight,
            padding,
            problemType,
        } = params;

        const plusSignSize = 18; // 加号大小（缩小）
        const minusSignSize = 18; // 减号大小（缩小）
        const equalsSignSize = 18; // 等号大小（缩小）
        const spacing = 8; // 加号左右间距（方便修改和调试）
        const answerBoxWidth = 34; // 答案框宽度
        const answerBoxHeight = 34; // 答案框高度

        // 绘制右侧答案框边框
        ctx.strokeStyle = '#999';
        ctx.lineWidth = 1;
        this.drawRoundedRectInternal(
            ctx,
            rightBoxX,
            boxY,
            rightBoxWidth,
            boxHeight,
            borderRadius,
            true,
        );

        const rightBoxCenterY = boxY + boxHeight / 2;
        const rightBoxAvailableWidth = rightBoxWidth - padding * 2;
        const answerStartY = rightBoxCenterY - answerBoxHeight / 2;

        // 根据问题类型确定运算符号大小
        const operatorSignSize =
            problemType === 'addition' ? plusSignSize : minusSignSize;

        // 计算总宽度并水平居中（加法和减法逻辑相同）
        const totalAnswerWidth =
            answerBoxWidth +
            spacing +
            operatorSignSize +
            spacing +
            answerBoxWidth +
            spacing +
            equalsSignSize +
            spacing +
            answerBoxWidth;
        const answerStartX =
            rightBoxX +
            padding +
            (rightBoxAvailableWidth - totalAnswerWidth) / 2;

        // 计算各个元素的位置
        const box1X = answerStartX;
        const operatorX = box1X + answerBoxWidth + spacing;
        const box2X = operatorX + plusSignSize + spacing;
        const equalsX = box2X + answerBoxWidth + spacing;
        const box3X = equalsX + equalsSignSize + spacing;

        // 绘制第一个方框（圆角）
        this.drawAnswerBox(
            ctx,
            box1X,
            answerStartY,
            answerBoxWidth,
            answerBoxHeight,
        );

        // 绘制运算符号（加号或减号）
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 2;
        ctx.beginPath();
        if (problemType === 'addition') {
            // 加号：横线和竖线
            ctx.moveTo(operatorX, rightBoxCenterY);
            ctx.lineTo(operatorX + operatorSignSize, rightBoxCenterY);
            ctx.moveTo(
                operatorX + operatorSignSize / 2,
                rightBoxCenterY - operatorSignSize / 2,
            );
            ctx.lineTo(
                operatorX + operatorSignSize / 2,
                rightBoxCenterY + operatorSignSize / 2,
            );
        } else {
            // 减号：只有横线
            ctx.moveTo(operatorX, rightBoxCenterY);
            ctx.lineTo(operatorX + operatorSignSize, rightBoxCenterY);
        }
        ctx.stroke();

        // 绘制第二个方框（圆角）
        this.drawAnswerBox(
            ctx,
            box2X,
            answerStartY,
            answerBoxWidth,
            answerBoxHeight,
        );

        // 绘制等号（缩短）
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.moveTo(equalsX, rightBoxCenterY - 3);
        ctx.lineTo(equalsX + equalsSignSize, rightBoxCenterY - 3);
        ctx.moveTo(equalsX, rightBoxCenterY + 3);
        ctx.lineTo(equalsX + equalsSignSize, rightBoxCenterY + 3);
        ctx.stroke();

        // 绘制第三个方框（答案，圆角）
        this.drawAnswerBox(
            ctx,
            box3X,
            answerStartY,
            answerBoxWidth,
            answerBoxHeight,
        );
    }

    /**
     * 根据图片类型设置图片大小
     */
    private getImageSize(imageType: 'twelve-animals' | 'fruits'): number {
        return imageType === 'twelve-animals' ? 40 : 36;
    }
}

export default AdditionDraw;
