import { SpriteFrame, Texture2D, ImageAsset, assetManager } from 'cc';
import { RuntimeLevelConfig } from '../types/LevelTypes';
import { NextLevelData } from '../types/ApiTypes';

/**
 * 进度回调类型
 * @param progress 进度值 0-1
 * @param message 进度消息
 */
export type ProgressCallback = (progress: number, message: string) => void;

/**
 * 关卡数据管理器
 * 单例模式，管理当前关卡和预加载关卡的图片资源
 * 不再依赖全量关卡列表，由外部传入 NextLevelData 驱动
 */
export class LevelDataManager {
    private static _instance: LevelDataManager | null = null;

    /** 运行时关卡配置缓存（按 levelId 索引） */
    private _levelConfigs: Map<string, RuntimeLevelConfig> = new Map();

    /** 图片缓存：URL -> SpriteFrame */
    private _imageCache: Map<string, SpriteFrame> = new Map();

    /** 正在加载中的关卡 ID 集合 */
    private _loadingLevels: Set<string> = new Set();

    /** 是否已初始化 */
    private _initialized: boolean = false;

    /**
     * 获取单例实例
     */
    static get instance(): LevelDataManager {
        if (!this._instance) {
            this._instance = new LevelDataManager();
        }
        return this._instance;
    }

    private constructor() {}

    /**
     * 初始化：加载首关图片
     * 由 PageLoading 在获取 game-data 后调用，传入 nextLevel 数据
     * @param nextLevel 首关数据（来自 game-data 接口）
     * @param onProgress 进度回调
     * @returns 是否初始化成功
     */
    async initialize(nextLevel: NextLevelData, onProgress?: ProgressCallback): Promise<boolean> {
        console.log(`[LevelDataManager] 开始初始化，加载关卡 ${nextLevel.level}`);

        try {
            onProgress?.(0.3, '正在加载游戏必备资源...');

            const config = await this._loadLevelFromData(nextLevel);
            if (!config) {
                console.error('[LevelDataManager] 初始化失败：图片加载失败');
                onProgress?.(0.3, '资源加载失败，请重新打开游戏');
                return false;
            }

            this._initialized = true;
            console.log('[LevelDataManager] 初始化完成');
            onProgress?.(0.8, '游戏资源加载完成');

            return true;
        } catch (error) {
            console.error('[LevelDataManager] 初始化失败:', error);
            onProgress?.(0.3, '网络异常，请重新打开游戏');
            return false;
        }
    }

    /**
     * 是否已初始化
     */
    isInitialized(): boolean {
        return this._initialized;
    }

    /**
     * 获取指定关卡配置（按 ID）
     * @param levelId 关卡 ID
     */
    getLevelConfig(levelId: string): RuntimeLevelConfig | null {
        return this._levelConfigs.get(levelId) ?? null;
    }

    /**
     * 用 enter 接口返回的数据更新运行时关卡配置（填充答案和线索）
     * @param levelId 关卡 ID
     * @param details enter 接口返回的详情
     */
    updateLevelDetails(levelId: string, details: {
        answer: string;
        image1Description: string | null;
        image2Description: string | null;
        punchline: string | null;
        hint1: string | null;
        hint2: string | null;
        hint3: string | null;
    }): void {
        const config = this._levelConfigs.get(levelId);
        if (!config) {
            console.warn(`[LevelDataManager] 关卡 ${levelId} 配置不存在，无法更新详情`);
            return;
        }

        this._levelConfigs.set(levelId, {
            ...config,
            answer: details.answer,
            image1Description: details.image1Description ?? config.image1Description,
            image2Description: details.image2Description ?? config.image2Description,
            punchline: details.punchline ?? config.punchline,
            clue1: details.hint1 ?? null,
            clue2: details.hint2 ?? null,
            clue3: details.hint3 ?? null,
        });

        console.log(`[LevelDataManager] 关卡 ${levelId} 详情已更新`);
    }

    /**
     * 加载并缓存一个关卡（同步等待图片加载完成）
     * 用于 game-data 返回的 nextLevel 或 complete 返回的 nextLevel
     * @param data NextLevelData
     * @returns 加载好的 RuntimeLevelConfig，失败返回 null
     */
    async ensureLevelReady(data: NextLevelData): Promise<RuntimeLevelConfig | null> {
        // 检查缓存
        const cached = this._levelConfigs.get(data.id);
        if (cached) {
            return cached;
        }

        // 检查是否正在加载
        if (this._loadingLevels.has(data.id)) {
            console.log(`[LevelDataManager] 关卡 ${data.id} 正在加载中...`);
            return null;
        }

        return this._loadLevelFromData(data);
    }

    /**
     * 预加载关卡图片（静默加载，不阻塞）
     * 用于 enter 返回的 preloadNextLevel
     * @param data NextLevelData
     */
    preloadLevel(data: NextLevelData): void {
        // 已缓存
        if (this._levelConfigs.has(data.id)) {
            console.log(`[LevelDataManager] 关卡 ${data.id} 已加载`);
            return;
        }

        // 正在加载
        if (this._loadingLevels.has(data.id)) {
            console.log(`[LevelDataManager] 关卡 ${data.id} 正在加载中`);
            return;
        }

        // 异步加载，不等待
        console.log(`[LevelDataManager] 开始预加载关卡 ${data.id}...`);
        this._loadLevelFromData(data).catch(err => {
            console.error(`[LevelDataManager] 预加载关卡失败:`, err);
        });
    }

    /**
     * 检查指定关卡图片是否已加载
     * @param levelId 关卡 ID
     */
    isLevelImageLoaded(levelId: string): boolean {
        return this._levelConfigs.has(levelId);
    }

    /**
     * 清除缓存
     */
    clearCache(): void {
        this._levelConfigs.clear();
        this._loadingLevels.clear();
        this._imageCache.clear();
        this._initialized = false;
        console.log('[LevelDataManager] 缓存已清除');
    }

    /**
     * 从 NextLevelData 加载图片并创建 RuntimeLevelConfig
     */
    private async _loadLevelFromData(data: NextLevelData): Promise<RuntimeLevelConfig | null> {
        this._loadingLevels.add(data.id);
        console.log(`[LevelDataManager] 开始加载关卡 ${data.id} 资源...`);

        try {
            const [spriteFrame1, spriteFrame2] = await Promise.all([
                this._loadImage(data.image1Url),
                this._loadImage(data.image2Url),
            ]);

            if (!spriteFrame1) {
                console.error(`[LevelDataManager] 加载关卡 ${data.id} 图片1失败`);
                return null;
            }

            const config = this._createRuntimeConfig(data, spriteFrame1, spriteFrame2);
            this._levelConfigs.set(data.id, config);
            console.log(`[LevelDataManager] 关卡 ${data.id} 资源加载完成`);

            return config;
        } finally {
            this._loadingLevels.delete(data.id);
        }
    }

    /**
     * 创建运行时关卡配置
     */
    private _createRuntimeConfig(data: NextLevelData, spriteFrame1: SpriteFrame | null, spriteFrame2: SpriteFrame | null): RuntimeLevelConfig {
        return {
            id: data.id,
            name: `第${data.level}关`,
            spriteFrame1,
            spriteFrame2,
            image1Description: data.image1Description,
            image2Description: data.image2Description,
            punchline: data.punchline,
            clue1: data.hint1,
            clue2: data.hint2,
            clue3: data.hint3,
            answer: data.answer,
            completed: false,
            timeLimit: data.timeLimit,
        };
    }

    /**
     * 加载远程图片为 SpriteFrame
     * @param url 图片 URL
     */
    private async _loadImage(url: string): Promise<SpriteFrame | null> {
        // 检查缓存
        const cached = this._imageCache.get(url);
        if (cached) {
            return cached;
        }

        return new Promise((resolve) => {
            assetManager.loadRemote<ImageAsset>(url, (err, imageAsset) => {
                if (err) {
                    console.error(`[LevelDataManager] 加载图片失败: ${url}`, err);
                    resolve(null);
                    return;
                }

                const texture = new Texture2D();
                texture.image = imageAsset;

                const spriteFrame = new SpriteFrame();
                spriteFrame.texture = texture;

                // 缓存
                this._imageCache.set(url, spriteFrame);

                resolve(spriteFrame);
            });
        });
    }
}
