import GridReasoningDraw from '../shared/service/gridReasoningDraw';
import { createFocusPage } from '../shared/common/focusPageMixin';
import {
    GridReasoningData,
    GridPosition,
} from '../shared/service/gridReasoningDraw';
import { NUMBER_COLORS } from '../../constants/colors';

createFocusPage({
    canvas: null as Canvas | null,
    ctx: null as RenderingContext | null,
    boxHeight: 0,
    boxWidth: 0,
    drawService: null as GridReasoningDraw | null,
    gridData: null as GridReasoningData | null,

    data: {
        pageTitle: '方格推理',
        functionId: '',
        hasContent: false,
        showShareDialog: false,
        currentOperatorType: 'mixed', // 'addition', 'subtraction', 'mixed'
        currentOperatorTypeName: '混合运算',
        operatorTypeActions: [
            { name: '加法运算', value: 'addition' },
            { name: '减法运算', value: 'subtraction' },
            { name: '混合运算', value: 'mixed' },
        ],
    },

    onLoad(options: { id?: string }) {
        const functionId = options.id || 'grid-reasoning';
        this.setData({
            functionId,
        });
        this.initPageInfo(functionId, '方格推理');
    },

    onReady() {
        this.initCanvas({
            createDrawService: (
                canvas: Canvas,
                ctx: RenderingContext,
                options?: Record<string, any>,
            ) => {
                return new GridReasoningDraw(canvas, ctx, options);
            },
            drawServiceOptions: {
                title: this.data.pageTitle,
                subTitle: '仔细观察，推理出合并方格并连线',
                functionId: this.data.functionId,
            },
            onCanvasReady: () => {
                // 初始随机生成
                this.onRandom();
            },
        });
    },

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

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

    /**
     * 选择运算类型
     */
    onSelectType(event: any) {
        const { name, value } = event.detail;
        this.setData({
            currentOperatorType: value,
            currentOperatorTypeName: name,
        });
        // 重新生成题目
        this.onRandom();
    },

    /**
     * 随机生成
     */
    onRandom() {
        // 随机选择一种颜色
        const colorKeys = Object.keys(NUMBER_COLORS).map(Number);
        const randomColorKey =
            colorKeys[Math.floor(Math.random() * colorKeys.length)];
        const selectedColor = NUMBER_COLORS[randomColorKey];

        const rows: Array<{
            grid1: GridPosition[];
            grid2: GridPosition[];
            operator: '+' | '-';
            result: GridPosition[];
        }> = [];

        const operatorType = this.data.currentOperatorType;

        // 生成5行的数据
        for (let i = 0; i < 5; i++) {
            // 根据选中的运算类型选择运算符
            let operator: '+' | '-';
            if (operatorType === 'addition') {
                operator = '+';
            } else if (operatorType === 'subtraction') {
                operator = '-';
            } else {
                // 混合运算：随机选择运算符
                operator = Math.random() > 0.5 ? '+' : '-';
            }

            // 生成第一个网格的涂色位置
            // 如果是减法运算，第一个网格至少要有2个位置
            let grid1Count: number;
            if (operator === '-') {
                grid1Count = Math.floor(Math.random() * 8) + 2; // 2-9个位置
            } else {
                grid1Count = Math.floor(Math.random() * 9) + 1; // 1-9个位置
            }
            const grid1Positions = this.generateRandomPositions(grid1Count);

            let grid2Positions: GridPosition[];
            let resultPositions: GridPosition[];

            if (operator === '+') {
                // 加法：生成第二个网格的涂色位置（至少1个）
                const grid2Count = Math.floor(Math.random() * 9) + 1;
                grid2Positions = this.generateRandomPositions(grid2Count);

                // 结果 = 并集
                resultPositions = this.unionPositions(
                    grid1Positions,
                    grid2Positions,
                );
            } else {
                // 减法：生成第二个网格的涂色位置（必须少于第一个）
                const maxGrid2Count = grid1Count - 1;
                const grid2Count =
                    Math.floor(Math.random() * maxGrid2Count) + 1;
                grid2Positions = this.generateRandomPositions(grid2Count);

                // 结果 = 差集
                resultPositions = this.subtractPositions(
                    grid1Positions,
                    grid2Positions,
                );
            }

            rows.push({
                grid1: grid1Positions,
                grid2: grid2Positions,
                operator: operator as '+' | '-',
                result: resultPositions,
            });
        }

        // 生成右侧答案选项
        // 右侧展示左侧5行的结果（result），顺序随机
        const answerOptions: Array<{
            positions: GridPosition[];
            rowIndex: number;
        }> = [];

        for (let i = 0; i < 5; i++) {
            answerOptions.push({
                positions: rows[i].result,
                rowIndex: i,
            });
        }

        // 随机打乱顺序
        answerOptions.sort(() => Math.random() - 0.5);

        this.gridData = {
            rows,
            answerOptions,
            color: selectedColor,
        };

        this.drawCanvas();
    },

    /**
     * 生成随机位置（不重复）
     */
    generateRandomPositions(count: number): GridPosition[] {
        const allPositions: GridPosition[] = [];
        for (let y = 0; y < 3; y++) {
            for (let x = 0; x < 3; x++) {
                allPositions.push({ x, y });
            }
        }

        // 随机打乱
        const shuffled = [...allPositions].sort(() => Math.random() - 0.5);

        // 返回前count个
        return shuffled.slice(0, count);
    },

    /**
     * 计算位置的并集
     */
    unionPositions(pos1: GridPosition[], pos2: GridPosition[]): GridPosition[] {
        const set = new Set<string>();
        const result: GridPosition[] = [];

        // 添加第一个数组的位置
        for (const pos of pos1) {
            const key = `${pos.x},${pos.y}`;
            if (!set.has(key)) {
                set.add(key);
                result.push(pos);
            }
        }

        // 添加第二个数组的位置（去重）
        for (const pos of pos2) {
            const key = `${pos.x},${pos.y}`;
            if (!set.has(key)) {
                set.add(key);
                result.push(pos);
            }
        }

        return result;
    },

    /**
     * 计算位置的差集（pos1 - pos2）
     */
    subtractPositions(
        pos1: GridPosition[],
        pos2: GridPosition[],
    ): GridPosition[] {
        const set2 = new Set<string>();
        for (const pos of pos2) {
            set2.add(`${pos.x},${pos.y}`);
        }

        const result: GridPosition[] = [];
        for (const pos of pos1) {
            const key = `${pos.x},${pos.y}`;
            if (!set2.has(key)) {
                result.push(pos);
            }
        }

        return result;
    },
});
