import {
    _decorator, Component, Node, Camera, Canvas, UITransform, view, Color,
    director, find, Layers,
} from 'cc';
import { GameController } from './GameController';
import { ViewController } from './controller/ViewController';
import { LineGridRenderer } from './gameplay/LineGridRenderer';
import { UIMain } from './ui/UIMain';
import { loadLevelDatabase, refreshLevelIdBounds, LEVEL_ID_BASE } from './level/LevelRegistry';
import { ThemeBackground } from './theme/ThemeBackground';
import { GridSnapHelper } from './level/GridSnapHelper';
import { GameplayDebugBar } from './ui/GameplayDebugBar';
import {
    CELL_PIXEL, CAMERA_ORTHO_HALF, DESIGN_WIDTH, DESIGN_HEIGHT,
} from './core/GridConstants';
import { applyEmbeddedDesignResolution } from './core/EmbeddedView';

export {
    CELL_PIXEL, CAMERA_ORTHO_HALF, DESIGN_WIDTH, DESIGN_HEIGHT,
} from './core/GridConstants';

const { ccclass, executionOrder } = _decorator;

/** HUD 专用层：与关卡 UI_2D 分离，不受主相机缩放/拖拽影响 */
const HUD_LAYER = Layers.Enum.UI_3D;
/** 背景专用层：BgCamera 固定正交，主相机缩放/平移时不跟随 */
const BG_LAYER = Layers.Enum.DEFAULT;

@ccclass('AppBootstrap')
@executionOrder(-100)
export class AppBootstrap extends Component {
    private readonly onCanvasResize = () => {
        const sync = (globalThis as { __tfrhSyncEmbeddedCanvas?: () => void }).__tfrhSyncEmbeddedCanvas;
        if (typeof sync === 'function') sync();
        else applyEmbeddedDesignResolution();
    };

    onDestroy() {
        view.off('canvas-resize', this.onCanvasResize, this);
    }

    async onLoad() {
        try {
            await this.bootstrap();
        } catch (e) {
            console.error('[AppBootstrap] 初始化失败', e);
        }
    }

    private async bootstrap() {
        console.log('[AppBootstrap] 开始初始化…');
        applyEmbeddedDesignResolution();
        view.on('canvas-resize', this.onCanvasResize, this);
        await loadLevelDatabase();
        refreshLevelIdBounds();

        const scene = director.getScene()!;
        find('UICanvas', scene)?.destroy();

        let mainCam = find('Main Camera', scene)?.getComponent(Camera) ?? null;
        if (!mainCam) {
            const camNode = new Node('Main Camera');
            camNode.parent = scene;
            mainCam = camNode.addComponent(Camera);
        } else if (mainCam.node.parent !== scene) {
            mainCam.node.parent = scene;
        }
        this.setupCamera(mainCam);
        mainCam.node.getComponent(ViewController) ?? mainCam.node.addComponent(ViewController);

        const size = view.getVisibleSize();
        const gameRoot = this.ensureGameRoot(scene, size, mainCam);
        this.ensureBgOverlay(scene, size, mainCam);
        const uiOverlay = this.ensureUIOverlay(scene, size, mainCam);
        this.bindAllCanvases(scene, mainCam);

        const host = this.node;
        const ctl = host.getComponent(GameController) ?? host.addComponent(GameController);

        let entrance = gameRoot.getChildByName('MainLevelEntrance');
        if (!entrance) {
            entrance = new Node('MainLevelEntrance');
            entrance.parent = gameRoot;
            entrance.addComponent(UITransform).setContentSize(size.width, size.height);
        }
        entrance.layer = Layers.Enum.UI_2D;
        LineGridRenderer.ensure(entrance);
        GridSnapHelper.purgeRuntimeGrids(entrance);

        ctl.mainLevelEntrance = entrance;
        if (ctl.initialLevelID <= 0) ctl.initialLevelID = LEVEL_ID_BASE;
        if (!ctl.inputLevel?.trim()) ctl.inputLevel = String(ctl.initialLevelID);

        this.removeRuntimeOverlayUI(gameRoot);
        gameRoot.getChildByName('UIMain')?.destroy();
        UIMain.ensure(uiOverlay);
        GameplayDebugBar.ensure(uiOverlay);
        ThemeBackground.purgeStaleNodes(entrance);

        // 关卡预制体由 SwitchLevel → createNewLevel 按需加载（loader 进关再下 levels_all）
        ctl.markReady();
        ctl.onBootstrapReady();
        console.log('[AppBootstrap] 引擎已就绪；SwitchLevel 进关时再加载资源/关卡库分片/预制体');
    }

    private ensureGameRoot(scene: Node, size: { width: number; height: number }, mainCam: Camera): Node {
        let gameRoot = find('GameRoot', scene) ?? find('Canvas', scene);
        if (!gameRoot) {
            gameRoot = new Node('GameRoot');
            gameRoot.parent = scene;
        }
        gameRoot.name = 'GameRoot';
        gameRoot.layer = Layers.Enum.UI_2D;
        gameRoot.active = true;
        const ui = gameRoot.getComponent(UITransform) ?? gameRoot.addComponent(UITransform);
        ui.setContentSize(size.width, size.height);

        const canvas = gameRoot.getComponent(Canvas) ?? gameRoot.addComponent(Canvas);
        canvas.cameraComponent = mainCam;
        canvas.alignCanvasWithScreen = true;
        return gameRoot;
    }

    /** 固定背景相机：先于主相机绘制，缩放/拖拽关卡时背景不动 */
    private ensureBgOverlay(scene: Node, size: { width: number; height: number }, mainCam: Camera): Node {
        let bgCamNode = find('BgCamera', scene);
        if (!bgCamNode) {
            bgCamNode = new Node('BgCamera');
            bgCamNode.parent = scene;
        }
        bgCamNode.setPosition(0, 0, 1000);
        bgCamNode.setRotationFromEuler(0, 0, 0);
        const bgCam = bgCamNode.getComponent(Camera) ?? bgCamNode.addComponent(Camera);
        bgCam.projection = Camera.ProjectionType.ORTHO;
        bgCam.orthoHeight = CAMERA_ORTHO_HALF;
        bgCam.near = 1;
        bgCam.far = 2000;
        bgCam.priority = mainCam.priority - 10;
        bgCam.clearFlags = Camera.ClearFlag.SOLID_COLOR;
        bgCam.clearColor = new Color(1, 1, 1, 255);
        bgCam.visibility = BG_LAYER;

        let overlay = find('BgOverlay', scene);
        if (!overlay) {
            overlay = new Node('BgOverlay');
            overlay.parent = scene;
        }
        overlay.layer = BG_LAYER;
        overlay.active = true;
        const ui = overlay.getComponent(UITransform) ?? overlay.addComponent(UITransform);
        ui.setContentSize(size.width, size.height);
        const canvas = overlay.getComponent(Canvas) ?? overlay.addComponent(Canvas);
        canvas.cameraComponent = bgCam;
        canvas.alignCanvasWithScreen = true;
        return overlay;
    }

    /** 固定 HUD 相机：缩放/平移主相机时按钮位置不变（对齐 Unity Screen Space Overlay） */
    private ensureUIOverlay(scene: Node, size: { width: number; height: number }, mainCam: Camera): Node {
        let uiCamNode = find('UICamera', scene);
        if (!uiCamNode) {
            uiCamNode = new Node('UICamera');
            uiCamNode.parent = scene;
        }
        uiCamNode.setPosition(0, 0, 1000);
        uiCamNode.setRotationFromEuler(0, 0, 0);
        const uiCam = uiCamNode.getComponent(Camera) ?? uiCamNode.addComponent(Camera);
        uiCam.projection = Camera.ProjectionType.ORTHO;
        uiCam.orthoHeight = CAMERA_ORTHO_HALF;
        uiCam.near = 1;
        uiCam.far = 2000;
        uiCam.priority = mainCam.priority + 10;
        uiCam.clearFlags = Camera.ClearFlag.DEPTH_STENCIL;
        uiCam.visibility = HUD_LAYER;

        let overlay = find('UIOverlay', scene);
        if (!overlay) {
            overlay = new Node('UIOverlay');
            overlay.parent = scene;
        }
        overlay.layer = HUD_LAYER;
        overlay.active = true;
        const ui = overlay.getComponent(UITransform) ?? overlay.addComponent(UITransform);
        ui.setContentSize(size.width, size.height);
        const canvas = overlay.getComponent(Canvas) ?? overlay.addComponent(Canvas);
        canvas.cameraComponent = uiCam;
        canvas.alignCanvasWithScreen = true;
        return overlay;
    }

    private bindAllCanvases(scene: Node, mainCam: Camera) {
        const uiCam = find('UICamera', scene)?.getComponent(Camera) ?? null;
        const bgCam = find('BgCamera', scene)?.getComponent(Camera) ?? null;
        for (const canvas of scene.getComponentsInChildren(Canvas)) {
            if (canvas.node.name === 'BgOverlay') {
                if (bgCam) canvas.cameraComponent = bgCam;
                canvas.alignCanvasWithScreen = true;
                continue;
            }
            if (canvas.node.name === 'UIOverlay') {
                if (uiCam) canvas.cameraComponent = uiCam;
                canvas.alignCanvasWithScreen = true;
                continue;
            }
            if (!canvas.cameraComponent?.isValid) {
                canvas.cameraComponent = mainCam;
            }
            canvas.alignCanvasWithScreen = true;
        }
        // 清理无相机 Canvas，避免 PointerEventDispatcher 读 null.cameraPriority
        for (const canvas of scene.getComponentsInChildren(Canvas)) {
            if (!canvas.cameraComponent) {
                canvas.destroy();
            }
        }
    }

    private removeRuntimeOverlayUI(gameRoot: Node) {
        gameRoot.getChildByName('Hint')?.destroy();
        gameRoot.getChildByName('LevelSwitchBar')?.destroy();
    }

    private setupCamera(cam: Camera) {
        const camNode = cam.node;
        camNode.setPosition(0, 0, 1000);
        camNode.setRotationFromEuler(0, 0, 0);
        camNode.layer = Layers.Enum.DEFAULT;
        cam.projection = Camera.ProjectionType.ORTHO;
        cam.orthoHeight = CAMERA_ORTHO_HALF;
        cam.near = 1;
        cam.far = 2000;
        cam.clearFlags = Camera.ClearFlag.DEPTH_STENCIL;
        cam.visibility = Layers.Enum.UI_2D;
    }

    switchLevelFromBootstrap() {
        const gc = this.getComponent(GameController);
        if (!gc) {
            console.warn('[AppBootstrap] 未找到 GameController，请先点预览 ▶');
            return;
        }
        gc.clickSwitchLevel();
    }
}
