import { useState } from "react";
import { useParams, useNavigate } from "react-router";
import {
  Film,
  Play,
  ChevronRight,
  Image as ImageIcon,
  MapPin,
  Sparkles,
  Edit2,
  Loader2,
  BookOpen,
  Users,
  Clapperboard,
  Video,
  Plus,
  X,
} from "lucide-react";
import { useProject } from "../../hooks/useProjects";
import {
  useOutline,
  useEpisodes,
  useCharacters,
  useScenes,
  useVideoTasks,
  useCreateEpisode,
  useUpdateEpisode,
} from "../../hooks/useAi";

type Tab = "outline" | "characters" | "storyboard" | "video";

export function ProjectDetail() {
  const { projectId } = useParams();
  const navigate = useNavigate();
  const pid = projectId ?? "";

  const { data: project, isLoading: projectLoading } = useProject(pid);
  const { data: outline } = useOutline(pid);
  const { data: episodes = [] } = useEpisodes(pid);
  const { data: characters = [] } = useCharacters(pid);
  const { data: scenes = [] } = useScenes(pid);
  const { data: videoTasks = [] } = useVideoTasks(pid);

  const [activeTab, setActiveTab] = useState<Tab>("outline");

  const tabs = [
    { id: "outline" as Tab, label: "大纲", icon: BookOpen },
    { id: "characters" as Tab, label: "角色/场景", icon: Users },
    { id: "storyboard" as Tab, label: "分镜", icon: Clapperboard },
    { id: "video" as Tab, label: "视频", icon: Video },
  ];

  if (projectLoading) {
    return (
      <div className="h-full flex items-center justify-center">
        <Loader2 className="w-8 h-8 animate-spin text-muted-foreground" />
      </div>
    );
  }

  return (
    <ProjectScriptView
      project={project}
      outline={outline}
      episodes={episodes}
      characters={characters}
      projectId={projectId}
      onNavigate={(path) => navigate(path)}
    />
  );

  return (
    <div className="h-full overflow-auto bg-background relative">
      {/* Header */}
      <div className="border-b border-border bg-card px-6 py-3">
        <div className="flex gap-4 items-center">
          <div className="w-20 aspect-[2/3] rounded-lg overflow-hidden bg-muted flex-shrink-0 flex items-center justify-center">
            {project?.coverUrl ? (
              <img src={project.coverUrl} alt="封面" className="w-full h-full object-cover" />
            ) : (
              <Film className="w-8 h-8 text-muted-foreground" />
            )}
          </div>

          <div className="flex-1">
            <div className="flex items-center gap-3 mb-2">
              <h1 className="text-lg font-semibold text-foreground">
                {project?.name ?? "加载中..."}
              </h1>
              {outline && (
                <span className="px-2 py-0.5 rounded bg-accent text-foreground text-xs border border-border">
                  {outline.genre}
                </span>
              )}
            </div>
            <div className="flex items-center gap-4 text-xs text-muted-foreground">
              {outline && <span>{outline.episodeCount}集</span>}
              {episodes.length > 0 && <span>已生成 {episodes.length} 集分集</span>}
              {characters.length > 0 && <span>{characters.length} 个角色</span>}
              {scenes.length > 0 && <span>{scenes.length} 个场景</span>}
              {project?.updatedAt && (
                <span>更新于 {new Date(project.updatedAt).toLocaleDateString("zh-CN")}</span>
              )}
            </div>
          </div>

          <div className="flex items-center gap-2 flex-shrink-0">
            {episodes.length === 0 ? (
              <button
                onClick={() => navigate(`/project/${projectId}/outline`)}
                className="px-4 py-2 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all text-sm flex items-center gap-2"
              >
                <Sparkles className="w-4 h-4" />
                生成大纲
              </button>
            ) : (
              <button
                onClick={() => navigate(`/project/${projectId}/storyboard`)}
                className="px-4 py-2 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all text-sm flex items-center gap-2"
              >
                进入工作台
                <ChevronRight className="w-4 h-4" />
              </button>
            )}
          </div>
        </div>

        {/* Tabs */}
        <div className="flex items-center gap-1 mt-3">
          {tabs.map((tab) => {
            const Icon = tab.icon;
            return (
              <button
                key={tab.id}
                onClick={() => setActiveTab(tab.id)}
                className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm transition-all ${
                  activeTab === tab.id
                    ? "bg-accent text-accent-foreground font-medium"
                    : "text-muted-foreground hover:text-foreground hover:bg-muted"
                }`}
              >
                <Icon className="w-4 h-4" />
                {tab.label}
              </button>
            );
          })}
        </div>
      </div>

      {/* Content */}
      <div className="p-6">
        <div className="max-w-6xl mx-auto">
          {activeTab === "outline" && (
            <OutlineTab
              outline={outline}
              episodes={episodes}
              projectId={projectId}
              onNavigateOutline={() => navigate(`/project/${projectId}/outline`)}
              onNavigateEpisode={(epId) => navigate(`/project/${projectId}/storyboard/${epId}`)}
            />
          )}
          {activeTab === "characters" && (
            <CharactersTab
              characters={characters}
              scenes={scenes}
              projectId={projectId}
              onNavigateChars={() => navigate(`/project/${projectId}/characters`)}
              onNavigateScenes={() => navigate(`/project/${projectId}/scenes`)}
            />
          )}
          {activeTab === "storyboard" && (
            <StoryboardTab episodes={episodes} projectId={projectId} />
          )}
          {activeTab === "video" && (
            <VideoTab videoTasks={videoTasks} projectId={projectId} />
          )}
        </div>
      </div>
    </div>
  );
}

function ProjectScriptView({
  project,
  outline,
  episodes,
  characters,
  projectId,
  onNavigate,
}: {
  project: import("../../lib/api/projects").ProjectDTO | undefined;
  outline: import("../../lib/api/ai").Outline | undefined;
  episodes: import("../../lib/api/ai").Episode[];
  characters: import("../../lib/api/ai").Character[];
  projectId?: string;
  onNavigate: (path: string) => void;
}) {
  const orderedEpisodes = [...episodes].sort(
    (a, b) => (a.episodeNumber || 0) - (b.episodeNumber || 0)
  );
  const episodeTotal = Math.max(
    outline?.episodeCount ?? 0,
    orderedEpisodes.length,
    orderedEpisodes.length === 0 ? 60 : 0
  );
  const [selectedEpisodeNo, setSelectedEpisodeNo] = useState(1);
  const selectedEpisode =
    orderedEpisodes.find((ep) => ep.episodeNumber === selectedEpisodeNo) ?? null;
  const selectedNo = selectedEpisodeNo;
  const uniqueTags = Array.from(
    new Set(
      [outline?.genre, project?.style, "爽文", "高燃", "悬疑", "玄幻"].filter(Boolean) as string[]
    )
  ).slice(0, 6);
  const defaultSynopsis =
    "一场意外让主角卷入仙门与妖族的暗潮之中。看似平凡的手艺成为破局关键，少年在一次次试炼里识破阴谋、守住同伴，也逐渐揭开自己身世与旧日神工之间的联系。";
  const fallbackCharacters = [
    {
      id: "fallback-1",
      name: "夏母",
      roleType: "关键人物",
      gender: "",
      age: "中年",
      personality: "温和坚韧，遇事有主见",
      costume: "朴素家常服",
    },
    {
      id: "fallback-2",
      name: "萧医师",
      roleType: "推动剧情",
      gender: "",
      age: "青年",
      personality: "理性克制，暗藏锋芒",
      costume: "青色长衫",
    },
  ];
  const displayCharacters = characters.length > 0 ? characters.slice(0, 4) : fallbackCharacters;
  const nextPath = episodes.length === 0 ? `/project/${projectId}/outline` : `/project/${projectId}/characters`;

  return (
    <div className="relative h-full overflow-auto bg-[#f7f8fb] text-[#111827]">
      <main className="mx-auto max-w-[860px] px-6 pb-32 pt-12">
        <section className="flex flex-col gap-8 sm:flex-row sm:items-start">
          <div className="h-[218px] w-[154px] flex-shrink-0 overflow-hidden rounded-[3px] bg-[#dfe3ea] shadow-[0_18px_48px_rgba(15,23,42,0.14)]">
            {project?.coverUrl ? (
              <img src={project.coverUrl} alt="项目封面" className="h-full w-full object-cover" />
            ) : (
              <div className="flex h-full w-full flex-col items-center justify-center bg-[linear-gradient(145deg,#262b36,#10131a)] text-white">
                <Film className="mb-3 h-9 w-9 opacity-70" />
                <span className="px-5 text-center text-sm font-semibold leading-5">
                  {project?.name ?? outline?.title ?? "剧本封面"}
                </span>
              </div>
            )}
          </div>

          <div className="min-w-0 flex-1 pt-1">
            <h1 className="mb-4 text-[28px] font-semibold leading-[1.22] tracking-normal text-[#0b1220]">
              {outline?.title ?? project?.name ?? "未命名项目"}
            </h1>
            <div className="mb-5 grid grid-cols-2 gap-x-8 gap-y-2 text-[13px] leading-6 text-[#6b7280] sm:grid-cols-4">
              <span>集数：{outline?.episodeCount ?? episodeTotal} 集</span>
              <span>比例：{project?.aspectRatio ?? "16:9"}</span>
              <span>清晰度：{project?.resolution ?? "720p"}</span>
              <span>风格：{project?.style ?? outline?.genre ?? "待生成"}</span>
            </div>
            <div className="flex flex-wrap gap-2">
              {uniqueTags.map((tag) => (
                <span
                  key={tag}
                  className="rounded-full border border-[#e4e7ef] bg-white px-3 py-1 text-xs font-medium text-[#536079]"
                >
                  {tag}
                </span>
              ))}
            </div>
          </div>
        </section>

        <div className="my-10 h-px bg-[#e6e8ef]" />

        <section className="mb-11">
          <h2 className="mb-4 text-[17px] font-semibold text-[#0b1220]">大纲</h2>
          <p className="text-[14px] leading-8 text-[#384152]">
            {outline?.synopsis ?? project?.description ?? defaultSynopsis}
          </p>
        </section>

        <section className="mb-12">
          <h2 className="mb-5 text-[17px] font-semibold text-[#0b1220]">人物小传</h2>
          <div className="grid gap-x-12 gap-y-6 md:grid-cols-2">
            {displayCharacters.map((char) => (
              <article key={char.id} className="text-[14px] leading-7 text-[#384152]">
                <h3 className="mb-1 font-semibold text-[#111827]">{char.name}</h3>
                <p>
                  {char.roleType ? `${char.roleType}，` : ""}
                  {char.gender ? `${char.gender}，` : ""}
                  {char.age ? `${char.age}。` : ""}
                  {char.personality || "性格鲜明，与主线冲突和情感推进紧密相关。"}
                  {char.costume ? ` 服饰：${char.costume}。` : ""}
                </p>
              </article>
            ))}
          </div>
        </section>

        <section>
          <h2 className="mb-5 text-[17px] font-semibold text-[#0b1220]">分集剧情</h2>
          <div className="mb-7 grid grid-cols-8 gap-3 sm:grid-cols-10 md:grid-cols-12">
            {Array.from({ length: episodeTotal }, (_, index) => index + 1).map((num) => (
              <button
                key={num}
                type="button"
                onClick={() => setSelectedEpisodeNo(num)}
                className={`h-9 rounded-full text-sm font-medium transition-all ${
                  num === selectedNo
                    ? "bg-[#111827] text-white shadow-[0_8px_18px_rgba(17,24,39,0.2)]"
                    : "bg-white text-[#4b5563] ring-1 ring-[#e3e6ee] hover:bg-[#f1f3f7]"
                }`}
              >
                {num}
              </button>
            ))}
          </div>

          <article className="text-[14px] leading-8 text-[#384152]">
            <h3 className="mb-2 font-semibold text-[#111827]">
              第{selectedNo}集{selectedEpisode?.title ? `：${selectedEpisode.title}` : ""}
            </h3>
            <p className="mb-4">
              {selectedEpisode?.summary ??
                "本集承接上一段危机，主角在新的线索中发现关键异常，并由此推动人物关系、外部冲突和最终选择进一步升级。"}
            </p>
            <p className="whitespace-pre-wrap">
              {selectedEpisode?.script ??
                "镜头从喧闹的街巷切入，主角察觉到细微异动。几句试探之后，暗处的矛盾浮出水面，众人的立场开始分化。主角在压力下做出决定，为下一集的分镜和视觉呈现留下清晰的动作线。"}
            </p>
          </article>
        </section>
      </main>

      <div className="pointer-events-none fixed bottom-8 left-0 right-0 z-20 flex justify-center px-6">
        <div className="pointer-events-auto flex w-full max-w-[520px] items-center justify-center">
          <button
            type="button"
            onClick={() => onNavigate(nextPath)}
            className="h-12 min-w-[260px] rounded-full bg-[#0b0f17] px-10 text-[15px] font-semibold text-white shadow-[0_18px_46px_rgba(17,24,39,0.3)] transition-transform hover:scale-[1.01] active:scale-[0.99]"
          >
            {episodes.length === 0 ? "生成分集" : "进入下一步"}
          </button>
        </div>
      </div>
    </div>
  );
}

// ---- Outline Tab ----
function OutlineTab({
  outline,
  episodes,
  projectId,
  onNavigateOutline,
  onNavigateEpisode,
}: {
  outline: import("../../lib/api/ai").Outline | undefined;
  episodes: import("../../lib/api/ai").Episode[];
  projectId?: string;
  onNavigateOutline: () => void;
  onNavigateEpisode: (epId: string) => void;
}) {
  if (!outline) {
    return (
      <div className="rounded-xl border border-dashed border-border bg-card p-12 text-center">
        <BookOpen className="w-12 h-12 text-muted-foreground mx-auto mb-4" />
        <h3 className="text-lg font-medium text-foreground mb-2">尚未生成大纲</h3>
        <p className="text-sm text-muted-foreground mb-6">上传剧本后，AI 可自动生成大纲和分集</p>
        <button
          onClick={onNavigateOutline}
          className="px-6 py-2.5 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all flex items-center gap-2 mx-auto"
        >
          <Sparkles className="w-4 h-4" />
          前往生成大纲
        </button>
      </div>
    );
  }

  return (
    <div>
      {/* Outline Card */}
      <div className="mb-8">
        <div className="flex items-center justify-between mb-4">
          <h2 className="text-lg font-semibold text-foreground">剧本大纲</h2>
          <button
            onClick={onNavigateOutline}
            className="text-sm text-primary hover:underline flex items-center gap-1"
          >
            <Edit2 className="w-3 h-3" />
            编辑
          </button>
        </div>
        <div className="rounded-xl border border-border bg-card p-6">
          <h3 className="text-base font-semibold text-foreground mb-2">{outline.title}</h3>
          <div className="flex items-center gap-3 mb-3 text-sm text-muted-foreground">
            <span>类型：{outline.genre}</span>
            <span>·</span>
            <span>{outline.episodeCount} 集</span>
          </div>
          <p className="text-sm text-foreground leading-relaxed">{outline.synopsis}</p>
        </div>
      </div>

      {/* Episode List */}
      <EpisodeListSection
        episodes={episodes}
        projectId={projectId}
        outlineExists={!!outline}
        onNavigateEpisode={onNavigateEpisode}
        onNavigateOutline={onNavigateOutline}
      />
    </div>
  );
}

// ---- Episode List with Edit/Create ----
type EpisodeDraft = {
  id?: string;
  episodeNumber: number;
  title: string;
  summary: string;
  script: string;
};

function EpisodeListSection({
  episodes,
  projectId,
  outlineExists,
  onNavigateEpisode,
  onNavigateOutline,
}: {
  episodes: import("../../lib/api/ai").Episode[];
  projectId?: string;
  outlineExists: boolean;
  onNavigateEpisode: (epId: string) => void;
  onNavigateOutline: () => void;
}) {
  const pid = projectId ?? "";
  const createMutation = useCreateEpisode(pid);
  const updateMutation = useUpdateEpisode(pid);
  const [draft, setDraft] = useState<EpisodeDraft | null>(null);

  const nextNumber =
    episodes.length === 0
      ? 1
      : Math.max(...episodes.map((e) => e.episodeNumber || 0)) + 1;

  const openCreate = () =>
    setDraft({ episodeNumber: nextNumber, title: "", summary: "", script: "" });

  const openEdit = (ep: import("../../lib/api/ai").Episode) =>
    setDraft({
      id: ep.id,
      episodeNumber: ep.episodeNumber,
      title: ep.title ?? "",
      summary: ep.summary ?? "",
      script: ep.script ?? "",
    });

  const submit = async () => {
    if (!draft) return;
    if (!draft.episodeNumber || draft.episodeNumber <= 0) return;
    const payload = {
      episodeNumber: draft.episodeNumber,
      title: draft.title,
      summary: draft.summary,
      script: draft.script,
    };
    if (draft.id) {
      await updateMutation.mutateAsync({ id: draft.id, patch: payload });
    } else {
      await createMutation.mutateAsync(payload);
    }
    setDraft(null);
  };

  if (episodes.length === 0) {
    return (
      <>
        {outlineExists && (
          <div className="rounded-xl border border-dashed border-border bg-card p-8 text-center">
            <p className="text-sm text-muted-foreground mb-4">大纲已生成，可由 AI 生成分集，或手动新增</p>
            <div className="flex items-center gap-3 justify-center">
              <button
                onClick={onNavigateOutline}
                className="px-5 py-2 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all text-sm flex items-center gap-2"
              >
                <Sparkles className="w-4 h-4" />
                生成分集
              </button>
              <button
                onClick={openCreate}
                className="px-5 py-2 rounded-lg border border-border bg-card text-foreground hover:bg-muted transition-all text-sm flex items-center gap-2"
              >
                <Plus className="w-4 h-4" />
                手动新增一集
              </button>
            </div>
          </div>
        )}
        {draft && (
          <EpisodeEditModal
            draft={draft}
            setDraft={setDraft}
            onClose={() => setDraft(null)}
            onSubmit={submit}
            saving={createMutation.isPending || updateMutation.isPending}
          />
        )}
      </>
    );
  }

  return (
    <div>
      <div className="flex items-center justify-between mb-4">
        <h2 className="text-lg font-semibold text-foreground">
          分集列表 ({episodes.length} 集)
        </h2>
        <button
          onClick={openCreate}
          className="text-sm text-primary hover:underline flex items-center gap-1"
        >
          <Plus className="w-4 h-4" />
          新增一集
        </button>
      </div>
      <div className="grid grid-cols-3 gap-4">
        {episodes.map((ep) => (
          <div
            key={ep.id}
            onClick={() => onNavigateEpisode(ep.id)}
            className="relative rounded-xl border border-border bg-card p-4 hover:border-primary transition-colors cursor-pointer"
          >
            <button
              onClick={(e) => {
                e.stopPropagation();
                openEdit(ep);
              }}
              className="absolute top-2 right-2 p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
              title="编辑本集"
            >
              <Edit2 className="w-3.5 h-3.5" />
            </button>
            <div className="flex items-center gap-2 mb-2">
              <span className="text-xs font-medium text-muted-foreground bg-accent px-2 py-0.5 rounded">
                第 {ep.episodeNumber} 集
              </span>
            </div>
            <h3 className="font-medium text-foreground text-sm mb-1 pr-6">{ep.title}</h3>
            <p className="text-xs text-muted-foreground line-clamp-3">{ep.summary}</p>
          </div>
        ))}
      </div>
      {draft && (
        <EpisodeEditModal
          draft={draft}
          setDraft={setDraft}
          onClose={() => setDraft(null)}
          onSubmit={submit}
          saving={createMutation.isPending || updateMutation.isPending}
        />
      )}
    </div>
  );
}

function EpisodeEditModal({
  draft,
  setDraft,
  onClose,
  onSubmit,
  saving,
}: {
  draft: EpisodeDraft;
  setDraft: (d: EpisodeDraft) => void;
  onClose: () => void;
  onSubmit: () => void;
  saving: boolean;
}) {
  const isEdit = !!draft.id;
  return (
    <div className="fixed inset-0 bg-black/40 backdrop-blur-sm flex items-center justify-center z-50 p-6">
      <div className="bg-card rounded-2xl border border-border w-full max-w-xl max-h-[90vh] flex flex-col">
        <div className="flex items-center justify-between p-5 border-b border-border flex-shrink-0">
          <h3 className="text-base font-semibold text-foreground">
            {isEdit ? "编辑分集" : "新增分集"}
          </h3>
          <button
            onClick={onClose}
            className="p-1 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted transition-colors"
          >
            <X className="w-4 h-4" />
          </button>
        </div>
        <div className="p-5 space-y-4 overflow-auto">
          <div>
            <label className="block text-xs font-medium text-foreground mb-1.5">集数</label>
            <input
              type="number"
              min={1}
              value={draft.episodeNumber}
              onChange={(e) =>
                setDraft({ ...draft, episodeNumber: Number(e.target.value) || 0 })
              }
              className="w-32 px-3 py-2 rounded-lg border border-border bg-background text-foreground text-sm focus:outline-none focus:border-primary"
            />
            <p className="text-xs text-muted-foreground mt-1">允许重复，请自行确保唯一</p>
          </div>
          <div>
            <label className="block text-xs font-medium text-foreground mb-1.5">本集标题</label>
            <input
              type="text"
              value={draft.title}
              onChange={(e) => setDraft({ ...draft, title: e.target.value })}
              className="w-full px-3 py-2 rounded-lg border border-border bg-background text-foreground text-sm focus:outline-none focus:border-primary"
            />
          </div>
          <div>
            <label className="block text-xs font-medium text-foreground mb-1.5">剧情摘要</label>
            <textarea
              value={draft.summary}
              onChange={(e) => setDraft({ ...draft, summary: e.target.value })}
              rows={3}
              className="w-full px-3 py-2 rounded-lg border border-border bg-background text-foreground text-sm focus:outline-none focus:border-primary resize-none"
            />
          </div>
          <div>
            <label className="block text-xs font-medium text-foreground mb-1.5">本集剧本正文</label>
            <textarea
              value={draft.script}
              onChange={(e) => setDraft({ ...draft, script: e.target.value })}
              rows={8}
              className="w-full px-3 py-2 rounded-lg border border-border bg-background text-foreground text-sm focus:outline-none focus:border-primary resize-none font-mono"
            />
          </div>
        </div>
        <div className="flex items-center justify-end gap-2 p-5 border-t border-border flex-shrink-0">
          <button
            onClick={onClose}
            className="px-4 py-2 rounded-lg border border-border text-foreground hover:bg-muted transition-colors text-sm"
          >
            取消
          </button>
          <button
            onClick={onSubmit}
            disabled={saving || !draft.episodeNumber}
            className="px-4 py-2 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all text-sm flex items-center gap-2 disabled:opacity-60 disabled:cursor-not-allowed"
          >
            {saving && <Loader2 className="w-3.5 h-3.5 animate-spin" />}
            保存
          </button>
        </div>
      </div>
    </div>
  );
}

// ---- Characters Tab ----
function CharactersTab({
  characters,
  scenes,
  projectId,
  onNavigateChars,
  onNavigateScenes,
}: {
  characters: import("../../lib/api/ai").Character[];
  scenes: import("../../lib/api/ai").Scene[];
  projectId?: string;
  onNavigateChars: () => void;
  onNavigateScenes: () => void;
}) {
  const getMainCharacterImage = (char: import("../../lib/api/ai").Character) =>
    char.frontImageUrl ?? char.imageUrl ?? char.sideImageUrl ?? char.backImageUrl ?? null;

  return (
    <div className="space-y-8">
      {/* Characters */}
      <div>
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center gap-2">
            <Users className="w-5 h-5 text-primary" />
            <h2 className="text-lg font-semibold text-foreground">角色设定</h2>
            <span className="text-sm text-muted-foreground">({characters.length})</span>
          </div>
          <button onClick={onNavigateChars} className="text-sm text-primary hover:underline">
            管理角色
          </button>
        </div>

        {characters.length === 0 ? (
          <div className="rounded-xl border border-dashed border-border bg-card p-8 text-center">
            <p className="text-sm text-muted-foreground mb-4">暂无角色，去角色页面提取</p>
            <button
              onClick={onNavigateChars}
              className="px-5 py-2 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all text-sm flex items-center gap-2 mx-auto"
            >
              <Sparkles className="w-4 h-4" />
              AI 提取角色
            </button>
          </div>
        ) : (
          <div className="grid grid-cols-4 gap-4">
            {characters.slice(0, 8).map((char) => (
              <div
                key={char.id}
                onClick={onNavigateChars}
                className="rounded-xl border border-border bg-card p-4 text-center cursor-pointer hover:border-primary transition-colors"
              >
                <div className="w-20 h-20 rounded-full overflow-hidden mx-auto mb-3 bg-muted flex items-center justify-center">
                  {getMainCharacterImage(char) ? (
                    <img src={getMainCharacterImage(char) ?? ""} alt={char.name} className="w-full h-full object-cover" />
                  ) : (
                    <ImageIcon className="w-8 h-8 text-muted-foreground" />
                  )}
                </div>
                <div className="font-medium text-foreground text-sm mb-1">{char.name}</div>
                <div className="text-xs text-muted-foreground">{char.roleType}</div>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Scenes */}
      <div>
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center gap-2">
            <MapPin className="w-5 h-5 text-primary" />
            <h2 className="text-lg font-semibold text-foreground">场景设定</h2>
            <span className="text-sm text-muted-foreground">({scenes.length})</span>
          </div>
          <button onClick={onNavigateScenes} className="text-sm text-primary hover:underline">
            管理场景
          </button>
        </div>

        {scenes.length === 0 ? (
          <div className="rounded-xl border border-dashed border-border bg-card p-8 text-center">
            <p className="text-sm text-muted-foreground mb-4">暂无场景，去场景页面提取</p>
            <button
              onClick={onNavigateScenes}
              className="px-5 py-2 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all text-sm flex items-center gap-2 mx-auto"
            >
              <Sparkles className="w-4 h-4" />
              AI 提取场景
            </button>
          </div>
        ) : (
          <div className="grid grid-cols-3 gap-4">
            {scenes.slice(0, 6).map((scene) => (
              <div
                key={scene.id}
                onClick={onNavigateScenes}
                className="rounded-xl border border-border bg-card overflow-hidden cursor-pointer hover:border-primary transition-colors"
              >
                <div className="aspect-video bg-muted flex items-center justify-center">
                  {scene.imageUrl ? (
                    <img src={scene.imageUrl} alt={scene.name} className="w-full h-full object-cover" />
                  ) : (
                    <ImageIcon className="w-8 h-8 text-muted-foreground" />
                  )}
                </div>
                <div className="p-3 flex items-center justify-between">
                  <div className="font-medium text-foreground text-sm">{scene.name}</div>
                  <span className="text-xs text-muted-foreground px-2 py-0.5 rounded bg-muted">
                    {scene.sceneType === "indoor" ? "室内" : "室外"}
                  </span>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ---- Storyboard Tab ----
function StoryboardTab({
  episodes,
  projectId,
}: {
  episodes: import("../../lib/api/ai").Episode[];
  projectId?: string;
}) {
  const navigate = useNavigate();
  const [selectedEpId, setSelectedEpId] = useState<string | null>(
    episodes.length > 0 ? episodes[0].id : null
  );

  if (episodes.length === 0) {
    return (
      <div className="rounded-xl border border-dashed border-border bg-card p-12 text-center">
        <Clapperboard className="w-12 h-12 text-muted-foreground mx-auto mb-4" />
        <h3 className="text-lg font-medium text-foreground mb-2">尚未生成分集</h3>
        <p className="text-sm text-muted-foreground">先生成大纲和分集，再进入分镜工作台</p>
      </div>
    );
  }

  return (
    <div>
      <div className="flex items-center justify-between mb-4">
        <h2 className="text-lg font-semibold text-foreground">分镜工作台</h2>
        <button
          onClick={() => navigate(`/project/${projectId}/storyboard/${selectedEpId ?? episodes[0].id}`)}
          className="px-4 py-2 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all text-sm flex items-center gap-2"
        >
          进入分镜工作台
          <ChevronRight className="w-4 h-4" />
        </button>
      </div>

      <div className="flex items-center gap-2 mb-6 flex-wrap">
        {episodes.map((ep) => (
          <button
            key={ep.id}
            onClick={() => setSelectedEpId(ep.id)}
            className={`px-3 py-1.5 rounded-lg text-sm transition-all ${
              selectedEpId === ep.id
                ? "bg-primary text-white"
                : "bg-card border border-border text-foreground hover:border-primary"
            }`}
          >
            第 {ep.episodeNumber} 集
          </button>
        ))}
      </div>

      {selectedEpId && (
        <div
          onClick={() => navigate(`/project/${projectId}/storyboard/${selectedEpId}`)}
          className="rounded-xl border border-border bg-card p-6 text-center hover:border-primary transition-colors cursor-pointer"
        >
          <Clapperboard className="w-12 h-12 text-muted-foreground mx-auto mb-3" />
          <p className="text-sm text-muted-foreground">
            点击进入第 {episodes.find(e => e.id === selectedEpId)?.episodeNumber} 集分镜工作台
          </p>
        </div>
      )}
    </div>
  );
}

// ---- Video Tab ----
function VideoTab({
  videoTasks,
  projectId,
}: {
  videoTasks: import("../../lib/api/ai").AiTask[];
  projectId?: string;
}) {
  const navigate = useNavigate();

  if (videoTasks.length === 0) {
    return (
      <div className="rounded-xl border border-dashed border-border bg-card p-12 text-center">
        <Video className="w-12 h-12 text-muted-foreground mx-auto mb-4" />
        <h3 className="text-lg font-medium text-foreground mb-2">尚无视频任务</h3>
        <p className="text-sm text-muted-foreground mb-6">在视频生成页面提交生成任务</p>
        <button
          onClick={() => navigate(`/project/${projectId}/video`)}
          className="px-6 py-2.5 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all flex items-center gap-2 mx-auto"
        >
          <Sparkles className="w-4 h-4" />
          前往视频生成
        </button>
      </div>
    );
  }

  const statusConfig: Record<string, { label: string; color: string }> = {
    pending: { label: "排队中", color: "bg-yellow-500" },
    running: { label: "生成中", color: "bg-blue-500" },
    succeeded: { label: "已完成", color: "bg-green-500" },
    failed: { label: "失败", color: "bg-red-500" },
  };

  return (
    <div>
      <div className="flex items-center justify-between mb-6">
        <h2 className="text-lg font-semibold text-foreground">
          视频任务 ({videoTasks.length})
        </h2>
        <button
          onClick={() => navigate(`/project/${projectId}/video`)}
          className="px-4 py-2 rounded-lg bg-gradient-to-r from-[#5b5ff9] to-[#8b5ff9] text-white hover:shadow-md transition-all text-sm flex items-center gap-2"
        >
          视频生成页面
          <ChevronRight className="w-4 h-4" />
        </button>
      </div>

      <div className="grid grid-cols-3 gap-4">
        {videoTasks.map((task) => {
          const cfg = statusConfig[task.status] ?? { label: task.status, color: "bg-gray-400" };
          return (
            <div key={task.id} className="rounded-xl border border-border bg-card overflow-hidden">
              <div className="aspect-video bg-muted flex items-center justify-center relative">
                {task.resultVideoUrl ? (
                  <video src={task.resultVideoUrl} className="w-full h-full object-cover" controls />
                ) : (
                  <div className="text-center">
                    {task.status === "running" ? (
                      <Loader2 className="w-10 h-10 text-primary animate-spin mx-auto mb-2" />
                    ) : (
                      <Film className="w-10 h-10 text-muted-foreground mx-auto mb-2" />
                    )}
                  </div>
                )}
              </div>
              <div className="p-3 flex items-center justify-between">
                <span className="text-xs text-muted-foreground">
                  {new Date(task.createdAt).toLocaleDateString("zh-CN")}
                </span>
                <div className="flex items-center gap-1">
                  <div className={`w-2 h-2 rounded-full ${cfg.color}`} />
                  <span className="text-xs text-muted-foreground">{cfg.label}</span>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}
