import { signal, useSignal, useSignalEffect } from "@preact/signals";
import Phaser, { AUTO } from "phaser";
import { createContext } from "preact";
import { useContext, useEffect, useRef } from "preact/hooks";

import {
  FadeScene as FadeSceneClass,
  FADE_SCENE_KEY,
} from "../scenes/FadeScene";

import type { ReactiveScene } from "../scenes";
import type { ReadonlySignal } from "@preact/signals-core";

export interface SceneController {
  /** 启动场景（带淡入淡出过渡） */
  launch(sceneKey: string): Promise<void>;
  /** 重新启动当前场景（带淡入淡出过渡） */
  restart(): Promise<void>;
  /** 当前活跃场景 key */
  currentScene: ReadonlySignal<string | null>;
  /** 是否正在过渡 */
  isTransitioning: ReadonlySignal<boolean>;
}

export interface PhaserGameContext {
  game: Phaser.Game;
  sceneController: SceneController;
}

export const phaserContext =
  createContext<ReadonlySignal<PhaserGameContext> | null>(null);

export const defaultPhaserConfig: Phaser.Types.Core.GameConfig = {
  type: AUTO,
  width: 560,
  height: 560,
  parent: "phaser-container",
  backgroundColor: "#f9fafb",
  scene: [],
  disableContextMenu: true,
};

export interface PhaserGameProps {
  config?: Partial<Phaser.Types.Core.GameConfig>;
  /** 初始启动的场景 key */
  initialScene?: string;
  children?: preact.ComponentChildren;
}

export function PhaserGame(props: PhaserGameProps) {
  const gameSignal = useSignal<PhaserGameContext>({
    game: undefined!,
    sceneController: undefined!,
  });
  const initialSceneLaunched = useRef(false);

  useSignalEffect(() => {
    const config: Phaser.Types.Core.GameConfig = {
      ...defaultPhaserConfig,
      ...props.config,
    };
    const phaserGame = new Phaser.Game(config);

    // 添加 FadeScene 并启动它来初始化 overlay
    const fadeScene = new FadeSceneClass();
    phaserGame.scene.add(FADE_SCENE_KEY, fadeScene, true); // 改为 true 以触发 create

    // 创建 SceneController
    const currentScene = signal<string | null>(null);
    const isTransitioning = signal(false);

    const sceneController: SceneController = {
      async launch(sceneKey: string) {
        if (isTransitioning.value) {
          console.warn("SceneController: 正在进行场景切换");
          return;
        }

        // 等待场景注册完成（最多等待 100ms）
        let retries = 0;
        while (!phaserGame.scene.getScene(sceneKey) && retries < 10) {
          await new Promise((resolve) => setTimeout(resolve, 10));
          retries++;
        }

        // 验证场景是否已注册
        if (!phaserGame.scene.getScene(sceneKey)) {
          console.error(`SceneController: 场景 "${sceneKey}" 未注册`);
          return;
        }

        isTransitioning.value = true;
        const fade = phaserGame.scene.getScene(
          FADE_SCENE_KEY,
        ) as FadeSceneClass;

        // 淡出到黑色
        phaserGame.scene.bringToTop(FADE_SCENE_KEY);
        await fade.fadeOut(300);

        // 停止当前场景
        if (currentScene.value) {
          phaserGame.scene.stop(currentScene.value);
        }

        // 确保场景已注册后再启动
        // （场景应该已经在 PhaserScene 组件中注册）
        if (!phaserGame.scene.getScene(sceneKey)) {
          console.error(`SceneController: 场景 "${sceneKey}" 在切换时仍未注册`);
          isTransitioning.value = false;
          return;
        }

        // 启动新场景
        phaserGame.scene.start(sceneKey);
        currentScene.value = sceneKey;

        // 淡入
        await fade.fadeIn(300);
        isTransitioning.value = false;
      },
      async restart() {
        if (isTransitioning.value) {
          console.warn("SceneController: 正在进行场景切换");
          return;
        }

        if (!currentScene.value) {
          console.warn("SceneController: 没有当前场景，无法 restart");
          return;
        }

        const sceneKey = currentScene.value;
        const scene = phaserGame.scene.getScene(sceneKey);

        if (!scene) {
          console.error(`SceneController: 场景 "${sceneKey}" 不存在`);
          return;
        }

        isTransitioning.value = true;
        const fade = phaserGame.scene.getScene(
          FADE_SCENE_KEY,
        ) as FadeSceneClass;

        // 淡出到黑色
        phaserGame.scene.bringToTop(FADE_SCENE_KEY);
        await fade.fadeOut(300);

        // 重启当前场景
        scene.scene.restart();

        // 淡入
        await fade.fadeIn(300);
        isTransitioning.value = false;
      },
      currentScene,
      isTransitioning,
    };

    gameSignal.value = { game: phaserGame, sceneController };

    return () => {
      gameSignal.value = { game: undefined!, sceneController: undefined! };
      initialSceneLaunched.current = false;
      phaserGame.destroy(true);
    };
  });

  // 启动初始场景（仅一次）
  useEffect(() => {
    const ctx = gameSignal.value;
    if (
      !initialSceneLaunched.current &&
      props.initialScene &&
      ctx?.sceneController
    ) {
      initialSceneLaunched.current = true;
      // 使用 microtask 确保所有子组件的场景注册已完成
      Promise.resolve().then(() => {
        ctx.sceneController.launch(props.initialScene!);
      });
    }
  }, [gameSignal.value, props.initialScene]);

  return (
    <div id="phaser-container" className="w-full h-full">
      <phaserContext.Provider value={gameSignal}>
        {props.children}
      </phaserContext.Provider>
    </div>
  );
}

export interface PhaserSceneProps<TData = {}> {
  sceneKey?: string;
  scene: ReactiveScene<TData> | { new (): ReactiveScene<TData> };
  data?: TData;
  children?: any;
}

export const phaserSceneContext =
  createContext<ReadonlySignal<ReactiveScene> | null>(null);

export function PhaserScene<TData = {}>(props: PhaserSceneProps<TData>) {
  const phaserGameSignal = useContext(phaserContext);
  const sceneSignal = useSignal<ReactiveScene<TData>>();
  const registered = useRef(false);

  useSignalEffect(() => {
    if (!phaserGameSignal) return;
    const ctx = phaserGameSignal.value;
    if (!ctx?.game) return;

    const game = ctx.game;

    // 注册场景到 Phaser（但不启动）
    const scene = "scene" in props.scene ? props.scene : new props.scene();
    const sceneKey = props.sceneKey ?? scene.sys.settings.key;
    if (!game.scene.getScene(sceneKey)) {
      const initData = {
        ...props.data,
        phaserGame: phaserGameSignal,
        sceneController: ctx.sceneController,
      };
      game.scene.add(sceneKey, props.scene, false, initData);
    }

    sceneSignal.value = scene;
    registered.current = true;

    return () => {
      sceneSignal.value = undefined;
      registered.current = false;
      // 不在这里移除场景，让 SceneController 管理生命周期
    };
  });

  return (
    <phaserSceneContext.Provider
      value={sceneSignal as ReadonlySignal<ReactiveScene>}
    >
      {props.children}
    </phaserSceneContext.Provider>
  );
}
