// ============================================================
// useCanvasStore — 无限画布状态管理 (Zustand)
//
// 对应原版 CatalogModel + SelectionModel + CanvasStateMachine
// ============================================================

import { createContext, useContext, createElement, type ReactNode } from 'react';
import { createStore, useStore } from 'zustand';
import type { ICanvasDataSource, SidecarMetadata } from '../utils/ICanvasDataSource';
import {
    extractEpisodeName,
    extractShotName,
    groupKeyForPath,
} from '../utils/scanner';

// ---------- 公开类型 ----------

/** 阶段类型（按 UI Tab 顺序排列） */
export type StageType = 'Assets' | 'Storyboard' | 'Keyframe' | 'Video' | 'Audio' | 'LipSync';
export type AuditStatus = 'pending' | 'approved' | 'rework' | 'deprecated';
export type AssetTypeFilter = '全部' | '角色' | '道具' | '场景';
export type LayoutMode = 'grid' | 'single';
export type InteractionMode = 'BROWSE' | 'SELECT' | 'REORDER';

// ---------- CatalogItem ----------

/** 画布中单个文件条目的完整状态 */
export interface CatalogItem {
    id: number;
    path: string;
    fileName: string;
    ext: string;
    stage: StageType;
    episodeName: string;
    shotName: string;
    groupKey: string;
    metadata: SidecarMetadata | null;
    fileSize: number;
    modifiedAt: string;
    /** 已加载的缩略图 Blob URL */
    blobUrl?: string;
    /** 已加载的 LOD 级别 */
    loadedLevel?: number;
}

// ---------- Store State ----------

export interface CanvasState {
    // ── 工作区 ──
    workspaceRoot: string | null;

    // ── 目录导航 ──
    /** workspaceRoot 下的项目文件夹名列表 */
    projects: string[];
    /** 当前选中的项目名（非完整路径） */
    selectedProject: string | null;
    /** selectedProject/shots/ 下的集数名列表 */
    episodes: string[];
    /** 当前选中的集数名 */
    selectedEpisode: string | null;
    /** selectedProject/shots/episode/ 下的镜头名列表 */
    shots: string[];
    /** 当前选中的镜头名 */
    selectedShot: string | null;

    // ── Catalog ──
    items: CatalogItem[];
    totalCount: number;

    // ── Selection ──
    selectedIds: Set<number>;

    // ── Stage & Filters ──
    currentStage: StageType;
    keywordQuery: string;
    tagQuery: string;
    auditFilter: AuditStatus | 'all';
    assetTypeFilter: AssetTypeFilter;
    /** 仅显示收藏条目（metadata.favorite === true） */
    favoriteOnly: boolean;

    // ── Layout ──
    layoutMode: LayoutMode;
    cols: number;
    rowsPerPage: number;
    singleRowsPerPage: number;

    // ── Pagination ──
    currentPage: number;
    pageEpoch: number;

    // ── Canvas transform ──
    zoom: number;
    panOffset: { x: number; y: number };

    // ── Interaction mode ──
    interactionMode: InteractionMode;

    // ── Meta ──
    isScanning: boolean;
    scanProgress: { found: number; currentPath: string } | null;

    // ── Actions ──
    setWorkspace: (root: string | null) => void;
    /** 计算当前完整项目路径 */
    getProjectPath: () => string | null;
    setProjects: (projects: string[]) => void;
    selectProject: (name: string | null) => void;
    setEpisodes: (episodes: string[]) => void;
    selectEpisode: (name: string | null) => void;
    setShots: (shots: string[]) => void;
    selectShot: (name: string | null) => void;

    setStage: (stage: StageType) => void;
    setFilters: (
        filters: Partial<
            Pick<
                CanvasState,
                'keywordQuery' | 'tagQuery' | 'auditFilter' | 'assetTypeFilter' | 'favoriteOnly'
            >
        >,
    ) => void;
    setLayoutMode: (mode: LayoutMode) => void;
    setScanProgress: (progress: CanvasState['scanProgress']) => void;
    setIsScanning: (isScanning: boolean) => void;
    appendItems: (entries: Array<{ path: string; fileName: string; ext: string; fileSize: number; modifiedAt: string }>) => void;
    clearItems: () => void;
    gotoPage: (page: number) => void;
    setZoom: (zoom: number) => void;
    setPanOffset: (offset: { x: number; y: number }) => void;
    setInteractionMode: (mode: InteractionMode) => void;
    toggleSelection: (id: number) => void;
    selectAll: () => void;
    clearSelection: () => void;
    updateItemMetadata: (id: number, metadata: Partial<SidecarMetadata>) => void;
    loadThumbnail: (id: number, blobUrl: string, level: number) => void;
    /** 获取 dataSource（供 hooks 使用） */
    getDataSource: () => ICanvasDataSource;
}

// ---------- Store 逻辑工厂 ----------

function createCanvasStoreLogic(dataSource: ICanvasDataSource, initialWorkspace: string | null) {
    return createStore<CanvasState>()((set, get) => ({
        workspaceRoot: initialWorkspace,

        projects: [],
        selectedProject: null,
        episodes: [],
        selectedEpisode: null,
        shots: [],
        selectedShot: null,

        items: [],
        totalCount: 0,

        selectedIds: new Set(),

        currentStage: 'Storyboard',
        keywordQuery: '',
        tagQuery: '',
        auditFilter: 'all',
        assetTypeFilter: '全部',
        favoriteOnly: false,

        layoutMode: 'grid',
        cols: 9,
        rowsPerPage: 16,
        singleRowsPerPage: 16,

        currentPage: 1,
        pageEpoch: 0,

        zoom: 1.0,
        panOffset: { x: 0, y: 0 },

        interactionMode: 'BROWSE',

        isScanning: false,
        scanProgress: null,

        // ── Actions ──

        setWorkspace: (root) =>
            set({
                workspaceRoot: root,
                projects: [],
                selectedProject: null,
                episodes: [],
                selectedEpisode: null,
                shots: [],
                selectedShot: null,
                currentPage: 1,
                items: [],
                totalCount: 0,
            }),

        getProjectPath: () => {
            const { workspaceRoot, selectedProject } = get();
            if (!workspaceRoot || !selectedProject) return null;
            return `${workspaceRoot}\\${selectedProject}`;
        },

        setProjects: (projects) => set({ projects }),

        // 选中项目：立即清空 items 并标记扫描中，避免旧数据显示残留
        selectProject: (name) =>
            set({
                selectedProject: name,
                episodes: [],
                selectedEpisode: null,
                shots: [],
                selectedShot: null,
                items: [],
                totalCount: 0,
                isScanning: true,
            }),

        setEpisodes: (episodes) => set({ episodes }),

        // 选中集数：立即清空 items 并标记扫描中
        selectEpisode: (name) =>
            set({
                selectedEpisode: name,
                shots: [],
                selectedShot: null,
                items: [],
                totalCount: 0,
                isScanning: true,
            }),

        setShots: (shots) => set({ shots }),

        // 选中镜头：立即清空 items 并标记扫描中
        selectShot: (name) =>
            set({
                selectedShot: name,
                items: [],
                totalCount: 0,
                isScanning: true,
            }),

        // 切换阶段：立即清空 items 并标记扫描中
        setStage: (stage) =>
            set({ currentStage: stage, currentPage: 1, items: [], totalCount: 0, isScanning: true }),

        setFilters: (filters) => set(filters as Partial<CanvasState>),

        setLayoutMode: (mode) => set({ layoutMode: mode, currentPage: 1 }),

        setScanProgress: (progress) => set({ scanProgress: progress }),

        setIsScanning: (scanning) => set({ isScanning: scanning }),

        appendItems: (entries) => {
            const state = get();
            const nextId = state.items.length;
            const stage = state.currentStage;
            const newItems: CatalogItem[] = entries.map((entry, i) => ({
                id: nextId + i + 1,
                path: entry.path,
                fileName: entry.fileName,
                ext: entry.ext,
                stage,
                episodeName: extractEpisodeName(entry.path),
                shotName: extractShotName(entry.path),
                groupKey: groupKeyForPath(entry.path, stage),
                metadata: null,
                fileSize: entry.fileSize,
                modifiedAt: entry.modifiedAt,
            }));
            set({
                items: [...state.items, ...newItems],
                totalCount: state.items.length + newItems.length,
            });
        },

        clearItems: () => set({ items: [], totalCount: 0, currentPage: 1 }),

        gotoPage: (page) =>
            set({ currentPage: page, pageEpoch: get().pageEpoch + 1 }),

        setZoom: (zoom) => set({ zoom: Math.max(0.02, Math.min(16.0, zoom)) }),

        setPanOffset: (panOffset) => set({ panOffset }),

        setInteractionMode: (mode) => set({ interactionMode: mode }),

        toggleSelection: (id) => {
            const selected = new Set(get().selectedIds);
            if (selected.has(id)) selected.delete(id);
            else selected.add(id);
            set({ selectedIds: selected });
        },

        selectAll: () => {
            const ids = new Set(get().items.map((i) => i.id));
            set({ selectedIds: ids });
        },

        clearSelection: () => set({ selectedIds: new Set() }),

        updateItemMetadata: (id, partialMeta) => {
            set({
                items: get().items.map((item) =>
                    item.id === id
                        ? {
                              ...item,
                              metadata: {
                                  ...(item.metadata || {
                                      schema_version: 1,
                                      favorite: false,
                                      remark: '',
                                      description: '',
                                      tags: [],
                                      create_time: new Date().toISOString(),
                                      original_name: item.fileName,
                                  }),
                                  ...partialMeta,
                              } as SidecarMetadata,
                          }
                        : item,
                ),
            });
        },

        loadThumbnail: (id, blobUrl, level) => {
            set({
                items: get().items.map((item) =>
                    item.id === id ? { ...item, blobUrl, loadedLevel: level } : item,
                ),
            });
        },

        getDataSource: () => dataSource,
    }));
}

// ---------- Context & Provider ----------

type CanvasStore = ReturnType<typeof createCanvasStoreLogic>;

/** 模块级 Store 引用（供非组件代码如 useSidecarSync 同步读取状态） */
let _canvasStore: CanvasStore | null = null;

/** 获取原始 Store 实例（用于 .getState() 同步读取） */
export function getCanvasStore(): CanvasStore {
    if (!_canvasStore) {
        throw new Error('CanvasStore 尚未初始化，请在 CanvasStoreProvider 内部使用');
    }
    return _canvasStore;
}

const CanvasStoreContext = createContext<CanvasStore | null>(null);

/**
 * 创建 Canvas Store 和对应的 Provider 组件。
 * 接收 ICanvasDataSource 实例，注入到 Store 逻辑中。
 */
export function createCanvasStoreProvider(dataSource: ICanvasDataSource, initialWorkspace?: string | null) {
    const store = createCanvasStoreLogic(dataSource, initialWorkspace ?? null);
    _canvasStore = store;

    function CanvasStoreProvider({ children }: { children: ReactNode }) {
        return createElement(CanvasStoreContext.Provider, { value: store }, children);
    }

    return { CanvasStoreProvider, store };
}

// ---------- Hook ----------

/**
 * 从 Zustand Store 中选择状态。
 * 使用选择器模式，仅在选中状态变化时触发重渲染。
 *
 * 用法：
 *   const items = useCanvasStore(s => s.items);
 *   const zoom = useCanvasStore(s => s.zoom);
 */
export function useCanvasStore<T>(selector: (state: CanvasState) => T): T {
    const store = useContext(CanvasStoreContext);
    if (!store) {
        throw new Error('useCanvasStore 必须在 CanvasStoreProvider 内部使用');
    }
    return useStore(store, selector);
}
