/**
 * 按数字涂颜色绘制服务
 */

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

/**
 * 按数字涂颜色数据
 */
export interface NumberColorData {
    numbers: number[];
}

/**
 * 按数字涂颜色绘制服务
 */
class NumberColorDraw extends BaseDrawService {
    colorData: NumberColorData | null = null;

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

    /**
     * 绘制按数字涂颜色内容
     */
    async draw(
        colorData: NumberColorData,
        patternType: string = 'circle', // 'circle' 或 'caterpillar'
    ) {
        if (!colorData || !colorData.numbers) {
            return;
        }

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

    /**
     * 绘制内容区域
     */
    private async drawContent(params: {
        canvas: WechatMiniprogram.Canvas;
        ctx: RenderingContext;
        colorData: NumberColorData;
        canvasWidth: number;
        startY: number;
        patternType?: string; // 'circle' 或 'caterpillar'
    }): Promise<void> {
        const {
            ctx,
            colorData,
            canvasWidth,
            startY,
            patternType = 'circle',
        } = params;
        const { numbers } = colorData;

        const leftMargin = 24;
        const rightMargin = 24;
        const itemSpacing = 115; // 行间距
        const leftBoxWidth = 100;
        const rightBoxWidth = 420;
        const boxHeight = 80;
        const borderRadius = 12;
        const startYPos = startY + 20;

        // 获取所有可用颜色值
        const availableColors = getNumberColors();

        // 为每一行随机分配颜色，确保不重复
        const shuffledColors = [...availableColors];
        // Fisher-Yates 洗牌算法
        for (let i = shuffledColors.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [shuffledColors[i], shuffledColors[j]] = [
                shuffledColors[j],
                shuffledColors[i],
            ];
        }

        // 为每一行分配颜色（确保不重复）
        // 如果行数超过颜色数量，从剩余颜色中随机选择，但确保相邻行不同
        const rowColors: string[] = [];

        for (let i = 0; i < numbers.length; i++) {
            if (i < shuffledColors.length) {
                // 前 N 行（N <= 颜色数量）使用不同的颜色
                rowColors.push(shuffledColors[i]);
            } else {
                // 如果行数超过颜色数量，从剩余颜色中选择（确保与上一行不同）
                const remainingColors = shuffledColors.filter(
                    (color) => color !== rowColors[i - 1],
                );
                const randomColor =
                    remainingColors[
                        Math.floor(Math.random() * remainingColors.length)
                    ];
                rowColors.push(randomColor);
            }
        }

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

        // 绘制每一行
        for (let i = 0; i < numbers.length; i++) {
            const boxY = startYPos + i * itemSpacing;
            const number = numbers[i];
            const numberColor = rowColors[i]; // 使用随机分配的颜色
            const isFirstRow = i === 0;

            // 绘制左侧数字框（虚线）
            ctx.strokeStyle = '#999';
            ctx.lineWidth = 1;
            this.drawRoundedRectInternal(
                ctx,
                leftBoxX,
                boxY,
                leftBoxWidth,
                boxHeight,
                borderRadius,
                true,
            );

            // 绘制数字（带颜色）
            ctx.fillStyle = numberColor;
            ctx.font = `bold ${56}px "Microsoft Yahei"`;
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(
                String(number),
                leftBoxX + leftBoxWidth / 2,
                boxY + boxHeight / 2,
            );

            // 绘制右侧内容框（虚线）
            ctx.strokeStyle = '#999';
            ctx.lineWidth = 1;
            this.drawRoundedRectInternal(
                ctx,
                rightBoxX,
                boxY,
                rightBoxWidth,
                boxHeight,
                borderRadius,
                true,
            );

            // 根据模式绘制右侧内容
            if (patternType === 'circle') {
                this.drawCirclePattern(
                    ctx,
                    rightBoxX,
                    boxY,
                    rightBoxWidth,
                    boxHeight,
                    number,
                    numberColor,
                    isFirstRow,
                );
            } else if (patternType === 'caterpillar') {
                this.drawCaterpillarPattern(
                    ctx,
                    rightBoxX,
                    boxY,
                    rightBoxWidth,
                    boxHeight,
                    number,
                    numberColor,
                    isFirstRow,
                );
            }
        }
    }

    /**
     * 绘制圆圈模式的内容
     */
    private drawCirclePattern(
        ctx: RenderingContext,
        x: number,
        y: number,
        width: number,
        height: number,
        number: number,
        numberColor: string,
        isFirstRow: boolean,
    ) {
        const totalCircles = 10;
        const circleRadius = 16; // 固定半径
        const circleSpacing = 6; // 固定间距

        // 计算所有圆圈的总宽度
        const totalWidth =
            totalCircles * circleRadius * 2 +
            (totalCircles - 1) * circleSpacing;

        // 计算水平居中位置
        const startX = x + (width - totalWidth) / 2 + circleRadius;

        // 计算垂直居中位置
        const centerY = y + height / 2;

        // 绘制10个虚线圆圈（一行）
        for (let i = 0; i < totalCircles; i++) {
            const circleX = startX + i * (circleRadius * 2 + circleSpacing);

            // 绘制虚线圆圈
            ctx.strokeStyle = numberColor;
            ctx.lineWidth = 1;
            ctx.setLineDash([3, 3]);
            ctx.beginPath();
            ctx.arc(circleX, centerY, circleRadius, 0, Math.PI * 2);
            ctx.stroke();
            ctx.setLineDash([]);

            // 第一行：根据数字数量涂色
            if (isFirstRow && i < number) {
                ctx.fillStyle = numberColor;
                ctx.beginPath();
                ctx.arc(circleX, centerY, circleRadius - 1, 0, Math.PI * 2);
                ctx.fill();
            }
        }
    }

    /**
     * 绘制毛毛虫模式的内容
     */
    private drawCaterpillarPattern(
        ctx: RenderingContext,
        x: number,
        y: number,
        width: number,
        height: number,
        number: number,
        numberColor: string,
        isFirstRow: boolean,
    ) {
        const padding = 15;
        const headSize = 45; // 头部区域高度（用于垂直居中）
        const headRadius = 18; // 固定头部半径
        const bodyRadius = 16; // 固定身体半径

        if (isFirstRow) {
            // 第一行：绘制完整的毛毛虫（头部+身体）
            const headX = x + padding;
            const headY = y + (height - headSize) / 2;

            // 绘制头部
            this.drawCaterpillarHead(ctx, headX, headY, headSize, numberColor);

            // 计算头部的实际宽度（头部半径 * 2）
            const headWidth = headRadius * 2; // 头部的实际宽度 = 36

            // 绘制身体（从头部右侧边缘开始，留一点间距）
            const bodyStartX = headX + headWidth + 17; // 头部右边缘 + 5px间距
            const bodyStartY = headY + headSize / 2; // 与头部中心Y对齐
            this.drawCaterpillarBody(
                ctx,
                bodyStartX,
                bodyStartY,
                number,
                bodyRadius,
                numberColor,
            );
        } else {
            // 其他行：只绘制头部
            const headX = x + padding;
            const headY = y + (height - headSize) / 2;
            this.drawCaterpillarHead(ctx, headX, headY, headSize, numberColor);
        }
    }

    /**
     * 绘制毛毛虫头部
     */
    private drawCaterpillarHead(
        ctx: RenderingContext,
        x: number,
        y: number,
        size: number,
        color: string,
    ) {
        const headRadius = 18; // 固定头部半径
        const headCenterX = x + headRadius;
        const headCenterY = y + size / 2;

        // 绘制头部（圆形）
        ctx.fillStyle = color;
        ctx.beginPath();
        ctx.arc(headCenterX, headCenterY, headRadius, 0, Math.PI * 2);
        ctx.fill();

        // 绘制头部圆圈实线边框
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 1;
        ctx.setLineDash([]); // 确保是实线
        ctx.beginPath();
        ctx.arc(headCenterX, headCenterY, headRadius, 0, Math.PI * 2);
        ctx.stroke();

        // 绘制触角（在头部圆圈的正上方，带弧度的弯曲）
        const antennaLength = headRadius * 0.6;
        const antennaStartY = headCenterY - headRadius; // 头部圆圈的正上方
        const antennaOffset = headRadius * 0.3; // 触角左右偏移距离

        // 左侧触角：从顶部左侧开始，先向上，然后向左弯曲（带弧度）
        const leftAntennaStartX = headCenterX - antennaOffset;
        const leftAntennaStartY = antennaStartY;
        const leftAntennaMidY = leftAntennaStartY - antennaLength * 0.5; // 向上延伸的中点
        const leftAntennaEndX = leftAntennaStartX - antennaLength * 0.4; // 向左弯曲
        const leftAntennaEndY = leftAntennaMidY - antennaLength * 0.3; // 向上并向左

        // 右侧触角：从顶部右侧开始，先向上，然后向右弯曲（带弧度）
        const rightAntennaStartX = headCenterX + antennaOffset;
        const rightAntennaStartY = antennaStartY;
        const rightAntennaMidY = rightAntennaStartY - antennaLength * 0.5; // 向上延伸的中点
        const rightAntennaEndX = rightAntennaStartX + antennaLength * 0.4; // 向右弯曲
        const rightAntennaEndY = rightAntennaMidY - antennaLength * 0.3; // 向上并向右

        ctx.strokeStyle = '#000';
        ctx.lineWidth = 1.5;
        ctx.lineCap = 'round'; // 圆角端点

        // 绘制左侧触角（使用二次贝塞尔曲线实现平滑弧度）
        ctx.beginPath();
        ctx.moveTo(leftAntennaStartX, leftAntennaStartY);
        // 使用二次贝塞尔曲线：起点、控制点、终点
        // 控制点在中间位置，使曲线平滑向左弯曲
        const leftControlX = leftAntennaStartX - antennaLength * 0.2;
        const leftControlY = leftAntennaMidY;
        ctx.quadraticCurveTo(
            leftControlX,
            leftControlY,
            leftAntennaEndX,
            leftAntennaEndY,
        );
        ctx.stroke();

        // 绘制右侧触角（使用二次贝塞尔曲线实现平滑弧度）
        ctx.beginPath();
        ctx.moveTo(rightAntennaStartX, rightAntennaStartY);
        // 使用二次贝塞尔曲线：起点、控制点、终点
        // 控制点在中间位置，使曲线平滑向右弯曲
        const rightControlX = rightAntennaStartX + antennaLength * 0.2;
        const rightControlY = rightAntennaMidY;
        ctx.quadraticCurveTo(
            rightControlX,
            rightControlY,
            rightAntennaEndX,
            rightAntennaEndY,
        );
        ctx.stroke();

        // 绘制触角末端的小圆点
        ctx.fillStyle = '#000';
        ctx.beginPath();
        ctx.arc(leftAntennaEndX, leftAntennaEndY, 2, 0, Math.PI * 2);
        ctx.fill();
        ctx.beginPath();
        ctx.arc(rightAntennaEndX, rightAntennaEndY, 2, 0, Math.PI * 2);
        ctx.fill();

        // 绘制眼睛
        const eyeSize = headRadius * 0.15;
        const eyeOffsetX = headRadius * 0.25;
        const eyeOffsetY = headRadius * 0.22;
        ctx.fillStyle = '#fff';
        ctx.beginPath();
        ctx.arc(
            headCenterX - eyeOffsetX - 2,
            headCenterY - eyeOffsetY,
            eyeSize,
            0,
            Math.PI * 2,
        );
        ctx.fill();
        ctx.beginPath();
        ctx.arc(
            headCenterX + eyeOffsetX - 2,
            headCenterY - eyeOffsetY,
            eyeSize,
            0,
            Math.PI * 2,
        );
        ctx.fill();

        // 绘制眼珠
        ctx.fillStyle = '#000';
        ctx.beginPath();
        ctx.arc(
            headCenterX - eyeOffsetX - 2,
            headCenterY - eyeOffsetY,
            eyeSize * 0.6,
            0,
            Math.PI * 2,
        );
        ctx.fill();
        ctx.beginPath();
        ctx.arc(
            headCenterX + eyeOffsetX - 2,
            headCenterY - eyeOffsetY,
            eyeSize * 0.6,
            0,
            Math.PI * 2,
        );
        ctx.fill();

        // 绘制嘴巴（微笑）
        ctx.strokeStyle = '#000';
        ctx.lineWidth = 1.5;
        ctx.beginPath();
        ctx.arc(
            headCenterX - 2,
            headCenterY + headRadius * 0.22,
            headRadius * 0.3,
            0,
            Math.PI,
        );
        ctx.stroke();
    }

    /**
     * 绘制毛毛虫身体（带弧度的圆圈）
     */
    private drawCaterpillarBody(
        ctx: RenderingContext,
        startX: number,
        startY: number,
        count: number,
        bodyRadius: number,
        color: string,
    ) {
        const spacing = bodyRadius * 2; // 身体圆圈之间的间距（稍微重叠）
        const waveAmplitude = bodyRadius * 0.4; // 波浪幅度

        for (let i = 0; i < count; i++) {
            // 计算每个身体圆圈的位置（带弧度，形成弯曲效果）
            const baseX = startX + i * spacing;
            // 使用正弦函数创建波浪效果，使身体有弧度
            const waveOffset = Math.sin((i * Math.PI) / 2.5) * waveAmplitude;
            const bodyX = baseX;
            const bodyY = startY + waveOffset;

            // 绘制身体圆圈
            ctx.fillStyle = color;
            ctx.beginPath();
            ctx.arc(bodyX, bodyY, bodyRadius, 0, Math.PI * 2);
            ctx.fill();

            // 绘制边框（可选，根据设计需求）
            ctx.strokeStyle = '#000';
            ctx.lineWidth = 1;
            ctx.stroke();
        }
    }

    /**
     * 绘制圆角矩形（虚线边框）
     */
    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([6, 6]); // 虚线
        } else {
            ctx.setLineDash([]);
        }
        ctx.stroke();
        ctx.setLineDash([]); // 重置为实线
    }
}

export default NumberColorDraw;
