// ============================================================
// CanvasSidebar — 左侧导航边栏
//
// 从上到下依次为：
//   1. 项目下拉选择器（ProjectSelector）
//   2. 集数下拉选择器（EpisodeSelector，Assets 阶段隐藏）
//   3. 镜头号搜索输入框
//   4. 镜头单选列表（每项支持右键菜单，定义见 menus/shot-menu.ts）
//   5. 刷新镜头列表按钮
// ============================================================

import { useState, useCallback } from 'react';
import { logger } from '@/shared/utils/bus';
import { Input, Button, App, Modal } from 'antd';
import { SearchOutlined, ReloadOutlined, FolderOpenOutlined } from '@ant-design/icons';
import { useTheme } from '@/app/providers/ThemeProvider';
import { useCanvasStore } from '../../stores/useCanvasStore';
import { ProjectSelector } from './ProjectSelector';
import { EpisodeSelector } from './EpisodeSelector';
import { ContextMenu } from '@/shared/components/ContextMenu';
import { getShotMenuItems } from '../../controllers/menus';
import { DirectoryCreateModal } from './DirectoryCreateModal';

export function CanvasSidebar() {
    const { isDark } = useTheme();
    const { message } = App.useApp();

    // ── Store 订阅 ──
    const workspaceRoot = useCanvasStore((s) => s.workspaceRoot);
    const selectedProject = useCanvasStore((s) => s.selectedProject);
    const selectedEpisode = useCanvasStore((s) => s.selectedEpisode);
    const selectedShot = useCanvasStore((s) => s.selectedShot);
    const shots = useCanvasStore((s) => s.shots);
    const currentStage = useCanvasStore((s) => s.currentStage);
    const selectShot = useCanvasStore((s) => s.selectShot);
    const setShots = useCanvasStore((s) => s.setShots);
    const setWorkspace = useCanvasStore((s) => s.setWorkspace);
    const setProjects = useCanvasStore((s) => s.setProjects);
    const getDataSource = useCanvasStore((s) => s.getDataSource);

    // ── 本地状态 ──
    const [shotSearchQuery, setShotSearchQuery] = useState('');
    const [isRefreshing, setIsRefreshing] = useState(false);
    const [createShotOpen, setCreateShotOpen] = useState(false);

    const isAssets = currentStage === 'Assets';

    // ── 镜头搜索过滤 ──
    const filteredShots = shotSearchQuery.trim()
        ? shots.filter((s) => s.toLowerCase().includes(shotSearchQuery.toLowerCase()))
        : shots;

    // ── 选择镜头 ──
    const handleShotClick = useCallback(
        (shotName: string) => {
            selectShot(shotName);
        },
        [selectShot],
    );

    // ── 镜头目录基础路径 ──
    const shotsBasePath = workspaceRoot && selectedProject
        ? `${workspaceRoot}\\${selectedProject}\\shots`
        : '';

    // ── 刷新镜头列表 ──
    const handleRefreshShots = useCallback(async () => {
        if (!workspaceRoot || !selectedProject || !selectedEpisode) return;
        try {
            setIsRefreshing(true);
            const dataSource = getDataSource();
            const shotsPath = `${workspaceRoot}\\${selectedProject}\\shots\\${selectedEpisode}`;
            const updated = await dataSource.listSubdirs(shotsPath);
            setShots(updated);
            message.success(`镜头列表已刷新（${updated.length} 个镜头）`);
        } catch (err) {
            logger.warn('canvas', '刷新镜头列表失败', err instanceof Error ? err : undefined);
            message.error(`刷新失败: ${(err as Error).message}`);
        } finally {
            setIsRefreshing(false);
        }
    }, [workspaceRoot, selectedProject, selectedEpisode, getDataSource, setShots, message]);

    // ── 打开/切换工作区 ──
    const handleOpenWorkspace = async () => {
        try {
            const dataSource = getDataSource();
            const dir = await dataSource.openDirectoryDialog();
            if (dir) {
                setWorkspace(dir);
                try {
                    const projects = await dataSource.listSubdirs(dir);
                    setProjects(projects);
                } catch (err) {
                    logger.warn('canvas', '加载项目列表失败', err instanceof Error ? err : new Error(String(err)));
                }
            }
        } catch (err) {
            logger.warn('canvas', '打开目录失败', err instanceof Error ? err : undefined);
            message.error((err as Error).message || '打开目录失败');
        }
    };

    // ── 右键菜单操作 ──

    // 新建镜头
    const handleCreateShot = useCallback(async (dirName: string) => {
        if (!shotsBasePath) return;
        try {
            const dataSource = getDataSource();
            const episodePath = `${shotsBasePath}\\${selectedEpisode}`;
            await dataSource.createDirectory(episodePath, dirName);
            // 刷新镜头列表
            const updated = await dataSource.listSubdirs(episodePath);
            setShots(updated);
            // 自动选中
            selectShot(dirName);
            message.success(`镜头 "${dirName}" 已创建`);
        } catch (err) {
            logger.warn('canvas', '创建镜头失败', err instanceof Error ? err : undefined);
            message.error(`创建失败: ${(err as Error).message}`);
        }
    }, [shotsBasePath, selectedEpisode, getDataSource, setShots, selectShot, message]);

    // 重命名镜头
    const handleRenameShot = useCallback((_shotName: string) => {
        message.info('重命名功能待实现');
    }, [message]);

    // 删除镜头
    const handleDeleteShot = useCallback((shotName: string) => {
        if (!shotsBasePath || !selectedEpisode) return;
        Modal.confirm({
            title: '确认删除',
            content: `确定要删除镜头「${shotName}」及其所有内容吗？此操作不可撤销。`,
            okText: '删除',
            okType: 'danger',
            cancelText: '取消',
            onOk: async () => {
                try {
                    const dataSource = getDataSource();
                    const shotPath = `${shotsBasePath}\\${selectedEpisode}\\${shotName}`;
                    await dataSource.deleteFile(shotPath);
                    // 刷新列表
                    const episodePath = `${shotsBasePath}\\${selectedEpisode}`;
                    const updated = await dataSource.listSubdirs(episodePath);
                    setShots(updated);
                    message.success(`已删除镜头「${shotName}」`);
                } catch (err) {
                    logger.warn('canvas', '删除镜头失败', err instanceof Error ? err : undefined);
                    message.error(`删除失败: ${(err as Error).message}`);
                }
            },
        });
    }, [shotsBasePath, selectedEpisode, getDataSource, setShots, message]);

    // 在文件夹中打开
    const handleOpenShotFolder = useCallback((shotName: string) => {
        if (!shotsBasePath || !selectedEpisode) return;
        const shotPath = `${shotsBasePath}\\${selectedEpisode}\\${shotName}`;
        window.fileStorage?.showItemInFolder(shotPath);
    }, [shotsBasePath, selectedEpisode]);

    // 生成单个镜头项的右键菜单
    const getShotContextItems = useCallback((shotName: string) =>
        getShotMenuItems({
            canOperate: !!workspaceRoot && !!selectedProject && !!selectedEpisode,
            shotName,
            onNewShot: () => setCreateShotOpen(true),
            onRename: handleRenameShot,
            onDelete: handleDeleteShot,
            onOpenFolder: handleOpenShotFolder,
        }), [workspaceRoot, selectedProject, selectedEpisode, handleRenameShot, handleDeleteShot, handleOpenShotFolder]);

    // ── 样式变量 ──
    const bg = isDark ? '#0F0D21' : '#F5F3FF';
    const borderColor = isDark ? '#2D2A4A' : '#E5E0F0';
    const sectionBg = isDark ? '#15132B' : '#EBE8F5';
    const textColor = isDark ? '#C8C4E0' : '#4A4570';
    const dimColor = isDark ? '#6E6B90' : '#9CA3AF';
    const activeBg = isDark ? '#2D2A5A' : '#E8E4FF';
    const activeColor = isDark ? '#C4B5FD' : '#6D28D9';
    const hoverBg = isDark ? '#1E1B3B' : '#EDEAFA';

    return (
        <div
            style={{
                height: '100%',
                background: bg,
                borderRight: `1px solid ${borderColor}`,
                display: 'flex',
                flexDirection: 'column',
                overflow: 'hidden',
            }}
        >
            {/* ── 工作区选择 ── */}
            <div
                style={{
                    padding: '6px 8px',
                    borderBottom: `1px solid ${borderColor}`,
                    flexShrink: 0,
                }}
            >
                <Button
                    type="dashed"
                    size="small"
                    block
                    icon={<FolderOpenOutlined />}
                    onClick={() => void handleOpenWorkspace()}
                    style={{
                        fontSize: 13,
                        color: isDark ? '#C4B5FD' : '#4338CA',
                        borderColor: isDark ? '#3E3A6A' : '#C7D2FE',
                    }}
                >
                    {workspaceRoot ? '切换工作区' : '打开工作区'}
                </Button>
                {workspaceRoot && (
                    <div
                        style={{
                            marginTop: 4,
                            fontSize: 11,
                            color: dimColor,
                            textAlign: 'center',
                            overflow: 'hidden',
                            textOverflow: 'ellipsis',
                            whiteSpace: 'nowrap',
                        }}
                        title={workspaceRoot}
                    >
                        {workspaceRoot}
                    </div>
                )}
            </div>

            {/* ── 导航选择器 ── */}
            {workspaceRoot && (
                <div
                    style={{
                        padding: '8px 8px 4px',
                        display: 'flex',
                        flexDirection: 'column',
                        gap: 6,
                        flexShrink: 0,
                    }}
                >
                    <div style={{ fontSize: 11, fontWeight: 600, color: dimColor, marginBottom: -2 }}>
                        项目
                    </div>
                    <ProjectSelector />

                    {!isAssets && (
                        <>
                            <div style={{ fontSize: 11, fontWeight: 600, color: dimColor, marginBottom: -2, marginTop: 4 }}>
                                集数
                            </div>
                            <EpisodeSelector />
                        </>
                    )}
                </div>
            )}

            {/* ── 镜头搜索 ── */}
            {workspaceRoot && selectedEpisode && !isAssets && (
                <div
                    style={{
                        padding: '8px 8px 4px',
                        flexShrink: 0,
                    }}
                >
                    <Input
                        prefix={<SearchOutlined style={{ fontSize: 13, color: dimColor }} />}
                        placeholder="搜索镜头号…"
                        value={shotSearchQuery}
                        onChange={(e) => setShotSearchQuery(e.target.value)}
                        allowClear
                        size="small"
                        style={{
                            background: sectionBg,
                            borderColor: isDark ? '#3E3A6A' : '#D1D5DB',
                            color: textColor,
                            borderRadius: 4,
                            fontSize: 13,
                        }}
                    />
                </div>
            )}

            {/* ── 镜头列表（每项支持右键菜单） ── */}
            <div
                style={{
                    flex: 1,
                    overflowY: 'auto',
                    overflowX: 'hidden',
                    minHeight: 0,
                    padding: '2px 0',
                    scrollbarWidth: 'thin' as const,
                    scrollbarColor: isDark
                        ? '#3E3A6A transparent'
                        : '#C7D2FE transparent',
                }}
            >
                {isAssets ? (
                    <div
                        style={{
                            padding: '24px 12px',
                            fontSize: 13,
                            color: dimColor,
                            textAlign: 'center',
                        }}
                    >
                        资产阶段无需选择镜头
                    </div>
                ) : !selectedEpisode ? (
                    <div
                        style={{
                            padding: '24px 12px',
                            fontSize: 13,
                            color: dimColor,
                            textAlign: 'center',
                        }}
                    >
                        请先选择集数
                    </div>
                ) : filteredShots.length === 0 ? (
                    <div
                        style={{
                            padding: '16px 12px',
                            fontSize: 13,
                            color: dimColor,
                            textAlign: 'center',
                        }}
                    >
                        {shotSearchQuery.trim() ? '无匹配镜头' : '该集数下无镜头'}
                    </div>
                ) : (
                    <>
                        {/* 镜头计数 */}
                        <div
                            style={{
                                padding: '4px 12px',
                                fontSize: 11,
                                fontWeight: 600,
                                color: dimColor,
                            }}
                        >
                            镜头列表
                            <span style={{ fontWeight: 400, marginLeft: 4 }}>
                                ({filteredShots.length}{shotSearchQuery.trim() ? ` / ${shots.length}` : ''})
                            </span>
                        </div>
                        {filteredShots.map((shot) => {
                            const active = shot === selectedShot;
                            return (
                                <ContextMenu key={shot} items={getShotContextItems(shot)}>
                                    <div
                                        onClick={() => handleShotClick(shot)}
                                        style={{
                                            padding: '5px 12px',
                                            cursor: 'pointer',
                                            fontSize: 13,
                                            color: active ? activeColor : textColor,
                                            background: active ? activeBg : 'transparent',
                                            transition: 'background 0.15s',
                                            userSelect: 'none',
                                            borderLeft: active
                                                ? `3px solid ${activeColor}`
                                                : '3px solid transparent',
                                        }}
                                        onMouseEnter={(e) => {
                                            if (!active)
                                                (e.currentTarget as HTMLElement).style.background = hoverBg;
                                        }}
                                        onMouseLeave={(e) => {
                                            if (!active)
                                                (e.currentTarget as HTMLElement).style.background =
                                                    'transparent';
                                        }}
                                    >
                                        {shot}
                                    </div>
                                </ContextMenu>
                            );
                        })}
                    </>
                )}
            </div>

            {/* ── 刷新按钮（固定在底部） ── */}
            {workspaceRoot && selectedEpisode && !isAssets && (
                <div
                    style={{
                        padding: '8px',
                        borderTop: `1px solid ${borderColor}`,
                        flexShrink: 0,
                        background: isDark ? '#0F0D1E' : '#EDE9F6',
                    }}
                >
                    <Button
                        size="small"
                        block
                        icon={<ReloadOutlined spin={isRefreshing} />}
                        onClick={() => void handleRefreshShots()}
                        loading={isRefreshing}
                        style={{
                            fontSize: 13,
                            fontWeight: 500,
                            borderRadius: 4,
                            border: `1px solid ${isDark ? '#3E3A6A' : '#C7D2FE'}`,
                            background: isDark
                                ? 'rgba(62, 58, 106, 0.4)'
                                : 'rgba(199, 210, 254, 0.3)',
                            color: isDark ? '#C4B5FD' : '#4338CA',
                        }}
                    >
                        刷新镜头列表
                    </Button>
                </div>
            )}

            {/* 新建镜头 Modal */}
            <DirectoryCreateModal
                open={createShotOpen}
                title="新建镜头"
                onOk={handleCreateShot}
                onCancel={() => setCreateShotOpen(false)}
            />
        </div>
    );
}
