import { Node, UITransform, Layers, Sprite } from 'cc';
import { LevelConfig } from './LevelTypes';
import { VisualAssets, normalizeTheme } from '../visual/VisualAssets';
import { layoutLevelTiles, sortIsoTiles } from './TileLayout';
import { LevelTileLayout } from './LevelTileLayout';
import { LevelMapData } from './LevelMapData';
import { GridSnapHelper } from './GridSnapHelper';
import { getThemeBorderDecorKey } from '../theme/ThemeRegistry';
import { centerLevelRoot, syncTileNodesFromConfig } from './LevelTileSync';
import { mergeLevelConfigWithMapData } from './LevelConfigMerge';
import { resolveTileNameAtCell, normalizeGroundTile, normalizeBorderTile } from './TileKinds';

const UI_LAYER = Layers.Enum.UI_2D;

function resolveLevelTheme(config: LevelConfig): string {
    return normalizeTheme(config.theme || 'silu');
}

/** 关卡预制体在 Canvas 下正确显示：统一 UI 层、按 JSON 对齐格子、刷新贴图 */
export class LevelDisplay {
    /** 每关使用 config.theme 独立贴图，与全局 UI 主题无关 */
    static async prepare(levelRoot: Node, config: LevelConfig) {
        levelRoot.name = `Level_${config.levelID}`;
        GridSnapHelper.purgeRuntimeGrids(levelRoot);
        this.ensureUILayerTree(levelRoot);

        config = mergeLevelConfigWithMapData(config, levelRoot);
        const theme = resolveLevelTheme(config);
        const tileCount = syncTileNodesFromConfig(levelRoot, config);
        layoutLevelTiles(levelRoot, config);

        const tileNames = this.collectTileNames(config);
        await VisualAssets.preloadLevelTiles(theme, tileNames);
        await this.refreshTileSprites(levelRoot, config, theme);

        layoutLevelTiles(levelRoot, config);
        centerLevelRoot(levelRoot, config);

        let layout = levelRoot.getComponent(LevelTileLayout);
        if (!layout) layout = levelRoot.addComponent(LevelTileLayout);
        layout.setRuntimeConfig(config);
        layout.applyLayout();
        layout.scheduleOnce(() => {
            if (!levelRoot?.isValid) return;
            layoutLevelTiles(levelRoot, config);
            centerLevelRoot(levelRoot, config);
            GridSnapHelper.purgeRuntimeGrids(levelRoot);
        }, 0);

        this.syncMapDataComponent(levelRoot, config);
        GridSnapHelper.purgeRuntimeGrids(levelRoot);
        console.log(`[LevelDisplay] 关卡 ${config.levelID} 同步 ${tileCount} 格，地图主题=${theme}`);
    }

    static syncMapDataComponent(levelRoot: Node, config: LevelConfig) {
        const md = levelRoot.getComponent(LevelMapData);
        if (!md) return;
        md.levelID = config.levelID;
        md.theme = resolveLevelTheme(config);
        if (config.ground && Object.keys(config.ground).length > 0) {
            md.groundJson = JSON.stringify(config.ground);
        }
        if (config.border && Object.keys(config.border).length > 0) {
            md.borderJson = JSON.stringify(config.border);
        }
    }

    static collectTileNames(config: LevelConfig): string[] {
        const names = new Set<string>(['Baseblock', 'JumpBlock', 'WallBlock', 'kuai11']);
        const decorKey = getThemeBorderDecorKey(config.theme);
        if (decorKey) names.add(decorKey);
        for (const v of Object.values(config.ground ?? {})) {
            names.add(normalizeGroundTile(v));
        }
        for (const v of Object.values(config.border ?? {})) {
            names.add(normalizeBorderTile(v));
        }
        return Array.from(names);
    }

    static ensureUILayerTree(root: Node) {
        const walk = (node: Node | null | undefined) => {
            if (!node?.isValid) return;
            node.layer = UI_LAYER;
            node.active = true;
            let ui = node.getComponent(UITransform);
            if (!ui) ui = node.addComponent(UITransform);
            if (node === root || node.name === 'Ground' || node.name === 'Border') {
                ui.setAnchorPoint(0, 0);
                ui.setContentSize(1, 1);
            }
            for (const ch of node.children) walk(ch);
        };
        walk(root);
    }

    static sortIsoLayers(levelRoot: Node) {
        sortIsoTiles(levelRoot, true);
    }

    private static queueTileSprite(
        jobs: Promise<void>[],
        node: Node,
        tileName: string,
        cellX: number,
        cellY: number,
        theme: string,
    ) {
        jobs.push(VisualAssets.applyNamedTile(node, tileName, 255, cellX, cellY, theme));
    }

    /** 仅刷新砖块贴图（实体已由 GameController 单独处理） */
    static async refreshTiles(levelRoot: Node, config: LevelConfig): Promise<void> {
        const theme = resolveLevelTheme(config);
        await VisualAssets.preloadLevelTiles(theme, this.collectTileNames(config));
        await this.refreshTileSprites(levelRoot, config, theme);
    }

    static async refreshTileSprites(levelRoot: Node, config: LevelConfig, theme: string) {
        const jobs: Promise<void>[] = [];

        const processLayer = (layer: Node | null, layerKind: 'ground' | 'border') => {
            if (!layer) return;
            for (const ch of layer.children) {
                if (!ch?.active) continue;
                const m = layerKind === 'border'
                    ? /^b_(-?\d+)_(-?\d+)$/.exec(ch.name)
                    : /^g_(-?\d+)_(-?\d+)$/.exec(ch.name);
                if (!m) continue;
                const key = `${m[1]},${m[2]}`;
                const cx = parseInt(m[1], 10);
                const cy = parseInt(m[2], 10);
                const tileName = resolveTileNameAtCell(layerKind, key, config.ground, config.border);
                this.queueTileSprite(jobs, ch, tileName, cx, cy, theme);
            }
        };

        processLayer(levelRoot.getChildByName('Ground'), 'ground');
        processLayer(levelRoot.getChildByName('Border'), 'border');

        const tiles = levelRoot.getChildByName('Tiles');
        if (tiles) {
            for (const ch of tiles.children) {
                if (!ch.active) continue;
                const mg = /^g_(-?\d+)_(-?\d+)$/.exec(ch.name);
                const mb = /^b_(-?\d+)_(-?\d+)$/.exec(ch.name);
                if (mg) {
                    const key = `${mg[1]},${mg[2]}`;
                    this.queueTileSprite(
                        jobs, ch,
                        resolveTileNameAtCell('ground', key, config.ground, config.border),
                        parseInt(mg[1], 10), parseInt(mg[2], 10), theme,
                    );
                } else if (mb) {
                    const key = `${mb[1]},${mb[2]}`;
                    this.queueTileSprite(
                        jobs, ch,
                        resolveTileNameAtCell('border', key, config.ground, config.border),
                        parseInt(mb[1], 10), parseInt(mb[2], 10), theme,
                    );
                }
            }
        }

        await Promise.all(jobs);
        layoutLevelTiles(levelRoot, config);

        let n = 0;
        const count = (node: Node) => {
            if (node.active && node.getComponent(Sprite)?.spriteFrame) n++;
            for (const c of node.children) count(c);
        };
        count(levelRoot);
        console.log(`[LevelDisplay] 关卡 ${config.levelID} 地图主题=${theme} 已刷新 ${n} 块`);
    }
}
