import BreakTenDraw from '../shared/service/breakTenDraw';
import {
    createMathPage,
    CanvasDataState,
} from '../shared/common/mathPageMixin';

createMathPage({
    canvas: null as Canvas | null,
    ctx: null as RenderingContext | null,
    boxHeight: 0,
    boxWidth: 0,
    drawService: null as BreakTenDraw | null,
    borrowTenData: null as {
        problems: Array<{
            minuend: number; // 被减数
            subtrahend: number; // 减数
            result: number;
        }>;
    } | null,

    data: {
        pageTitle: '借十法练习',
        functionId: '',
        hasContent: false,
        showShareDialog: false,
        currentMode: 'within-50', // 'within-30', 'within-50', 'within-100'
        currentModeName: '50以内',
        typeActions: [
            { name: '30以内', value: 'within-30' },
            { name: '50以内', value: 'within-50' },
            { name: '100以内', value: 'within-100' },
        ],
    } as CanvasDataState & {
        currentMode: string;
        currentModeName: string;
        typeActions: Array<{ name: string; value: string }>;
    },

    onLoad(options: { id?: string }) {
        const functionId = options.id || 'borrow-ten';
        this.initPageInfo(functionId, '借十法练习');
    },

    onReady() {
        this.initCanvas({
            createDrawService: (
                canvas: Canvas,
                ctx: RenderingContext,
                options?: Record<string, any>,
            ) => {
                return new BreakTenDraw(canvas, ctx, options);
            },
            drawServiceOptions: {
                mnemonic: '拆大数，借出10，减小数，加剩数', // 自定义口诀
            },
            onCanvasReady: () => {
                // 初始随机生成
                this.onRandom();
            },
        });
    },

    /**
     * 绘制Canvas内容
     */
    async drawCanvas() {
        if (!this.ctx || !this.drawService || !this.borrowTenData) {
            return;
        }

        try {
            await this.drawService.draw(this.borrowTenData);
            this.setData({ hasContent: true });
        } catch (error) {
            console.error('绘制失败:', error);
            this.setData({ hasContent: false });
        }
    },

    /**
     * 随机生成
     */
    onRandom() {
        // 根据当前模式确定被减数的最大值
        let maxMinuend = 30; // 默认30以内
        if (this.data.currentMode === 'within-50') {
            maxMinuend = 50;
        } else if (this.data.currentMode === 'within-100') {
            maxMinuend = 100;
        }

        // 按被减数分组，列出每个被减数对应的所有符合条件的减数组合
        const problemsByMinuend: Map<
            number,
            Array<{
                minuend: number;
                subtrahend: number;
                result: number;
            }>
        > = new Map();

        // 遍历所有可能的被减数（20到maxMinuend）和减数（1-10）组合
        for (let minuend = 20; minuend <= maxMinuend; minuend++) {
            const minuendOnes = minuend % 10; // 被减数的个位数

            for (let subtrahend = 1; subtrahend <= 10; subtrahend++) {
                // 检查条件：
                // 1. 被减数的个位 < 减数（借十法的关键要求：减数要大于被减数的个位数）
                // 2. 被减数 > 减数（确保结果大于0）
                if (minuendOnes < subtrahend && minuend > subtrahend) {
                    if (!problemsByMinuend.has(minuend)) {
                        problemsByMinuend.set(minuend, []);
                    }
                    problemsByMinuend.get(minuend)!.push({
                        minuend,
                        subtrahend,
                        result: minuend - subtrahend,
                    });
                }
            }
        }

        // 从每个被减数组中选择题目，确保每个被减数都有代表
        const problems: Array<{
            minuend: number;
            subtrahend: number;
            result: number;
        }> = [];

        // 获取所有被减数列表并打乱
        const minuends = Array.from(problemsByMinuend.keys());
        for (let i = minuends.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [minuends[i], minuends[j]] = [minuends[j], minuends[i]];
        }

        // 从每个被减数组中随机选择，确保分布均匀
        // 如果被减数数量 >= 9，每个被减数至少选1个；如果 < 9，尽量均匀分配
        const targetCount = 9;
        const minuendCount = minuends.length;

        if (minuendCount >= targetCount) {
            // 被减数数量足够，从每个被减数组中随机选择1个
            for (let i = 0; i < targetCount; i++) {
                const minuend = minuends[i];
                const problemsForMinuend = problemsByMinuend.get(minuend)!;
                const randomIndex = Math.floor(
                    Math.random() * problemsForMinuend.length,
                );
                problems.push(problemsForMinuend[randomIndex]);
            }
        } else {
            // 被减数数量不足，尽量均匀分配
            const perMinuend = Math.floor(targetCount / minuendCount);
            const remainder = targetCount % minuendCount;

            for (let i = 0; i < minuendCount; i++) {
                const minuend = minuends[i];
                const problemsForMinuend = problemsByMinuend.get(minuend)!;
                const count = perMinuend + (i < remainder ? 1 : 0); // 前remainder个多选1个

                // 从该被减数组中随机选择count个（不重复）
                const shuffled = [...problemsForMinuend];
                for (let j = shuffled.length - 1; j > 0; j--) {
                    const k = Math.floor(Math.random() * (j + 1));
                    [shuffled[j], shuffled[k]] = [shuffled[k], shuffled[j]];
                }

                for (let j = 0; j < Math.min(count, shuffled.length); j++) {
                    problems.push(shuffled[j]);
                }
            }
        }

        // 最后打乱所有题目顺序
        for (let i = problems.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [problems[i], problems[j]] = [problems[j], problems[i]];
        }

        this.borrowTenData = { problems };
        this.drawCanvas();
    },

    /** 选择类型 */
    onSelectType(event: any) {
        const { name, value } = event.detail;
        this.setData({
            currentMode: value,
            currentModeName: name,
        });
        // 重新生成数据
        this.onRandom();
    },
});
