import {
  ApiOutlined,
  ArrowLeftOutlined,
  AudioOutlined,
  CloseOutlined,
  CommentOutlined,
  CustomerServiceOutlined,
  DeploymentUnitOutlined,
  DownOutlined,
  EditOutlined,
  EllipsisOutlined,
  FontSizeOutlined,
  HistoryOutlined,
  BlockOutlined,
  InboxOutlined,
  PictureOutlined,
  PlayCircleOutlined,
  PlusOutlined,
  SearchOutlined,
  SettingOutlined,
  SoundOutlined,
  StarFilled,
  StarOutlined,
  VideoCameraOutlined,
} from "@ant-design/icons";
import { useMemo, useRef, useState, type CSSProperties, type PointerEvent, type ReactNode } from "react";
import "../../styles/pages/avatar-console.css";
import type { WebViewKey } from "../../types";
import {
  bringAvatarEditorLayerForward,
  createDefaultAvatarEditorLayers,
  moveAvatarEditorLayer,
  sendAvatarEditorLayerBackward,
  type AvatarEditorLayer,
  type AvatarEditorLayerId,
} from "./avatarEditorModel";
import {
  VOICE_CLONE_SCRIPT,
  createVoiceCloneDraft,
  voiceCloneLanguageOptions,
  voiceLibraryTabs,
  type VoiceLibraryTabKey,
} from "./voiceLibraryModel";
import {
  avatarTrainingScenarios,
  continueAvatarTraining,
  createAvatarTrainingDraft,
  selectAvatarTrainingScenario,
  type AvatarTrainingDraft,
  type AvatarTrainingScenarioKey,
} from "./avatarTrainingModel";

type ConsoleView = "explore" | "videos" | "chat" | "live" | "avatars" | "voices";
type BroadcastRatio = "16:9" | "9:16";
type EditorTool = "avatar" | "content" | "subtitle" | "background" | "sticker";

interface AvatarConsolePageProps {
  onOpenMore?: () => void;
  onSelectView?: (view: WebViewKey) => void;
}

interface ConsoleNavItem {
  key: ConsoleView;
  label: string;
  icon: JSX.Element;
}

interface AvatarCard {
  name: string;
  type: string;
  tone: string;
  background: string;
  accent: string;
}

interface VoiceCard {
  name: string;
  language: string;
  gender: string;
  description: string;
  gradient: string;
}

const productNav: ConsoleNavItem[] = [
  { key: "chat", label: "对话互动", icon: <CommentOutlined /> },
  { key: "live", label: "直播", icon: <VideoCameraOutlined /> },
];

const assetNav: ConsoleNavItem[] = [
  { key: "avatars", label: "形象库", icon: <CustomerServiceOutlined /> },
  { key: "voices", label: "声音库", icon: <AudioOutlined /> },
];

const quickNav: ConsoleNavItem[] = [
  { key: "explore", label: "探索", icon: <StarOutlined /> },
  { key: "videos", label: "我的视频", icon: <PlayCircleOutlined /> },
];

const editorTools: Array<{
  key: EditorTool;
  label: string;
  icon: JSX.Element;
}> = [
  { key: "avatar", label: "形象", icon: <CustomerServiceOutlined /> },
  { key: "content", label: "内容", icon: <SoundOutlined /> },
  { key: "subtitle", label: "字幕", icon: <FontSizeOutlined /> },
  { key: "background", label: "背景", icon: <PictureOutlined /> },
  { key: "sticker", label: "贴图", icon: <StarOutlined /> },
];

const avatarCards: AvatarCard[] = [
  { name: "萌娃陪伴", type: "对话数字人", tone: "儿童陪伴", background: "rgb(246 230 232)", accent: "rgb(225 108 118)" },
  { name: "心宁咨询", type: "对话数字人", tone: "心理咨询", background: "rgb(245 232 223)", accent: "rgb(196 126 86)" },
  { name: "健康小助理", type: "对话数字人", tone: "健康科普", background: "rgb(238 240 251)", accent: "rgb(98 111 205)" },
  { name: "口语陪练", type: "对话数字人", tone: "语言教学", background: "rgb(224 241 247)", accent: "rgb(67 141 167)" },
  { name: "文旅杭韵", type: "对话数字人", tone: "文旅讲解", background: "rgb(252 235 244)", accent: "rgb(198 91 137)" },
  { name: "街头潮燃", type: "对话数字人", tone: "年轻潮流", background: "rgb(230 239 245)", accent: "rgb(57 91 116)" },
  { name: "金融顾问", type: "商务数字人", tone: "专业顾问", background: "rgb(238 238 237)", accent: "rgb(73 80 92)" },
  { name: "情感陪伴", type: "对话数字人", tone: "温柔陪伴", background: "rgb(249 246 243)", accent: "rgb(188 119 93)" },
  { name: "心理治疗师", type: "对话数字人", tone: "疗愈咨询", background: "rgb(242 232 222)", accent: "rgb(181 117 78)" },
  { name: "灵舒", type: "2D图片训练数字人", tone: "温柔讲解", background: "rgb(221 232 238)", accent: "rgb(89 117 132)" },
  { name: "雅韵", type: "直播数字人", tone: "美妆导购", background: "rgb(253 230 218)", accent: "rgb(226 126 91)" },
  { name: "商务主持", type: "播报数字人", tone: "企业介绍", background: "rgb(225 233 249)", accent: "rgb(70 101 167)" },
];

const voiceCards: VoiceCard[] = [
  { name: "冷静女孩", language: "中英文", gender: "女", description: "沉着淡定，理智清晰", gradient: "linear-gradient(135deg, rgb(93 224 199), rgb(99 120 242))" },
  { name: "高亢直播女", language: "中英文", gender: "女", description: "洪亮昂扬，活力四射", gradient: "linear-gradient(135deg, rgb(108 213 198), rgb(255 194 104))" },
  { name: "激情男主播", language: "中英文", gender: "男", description: "热烈奔放，超强感染", gradient: "linear-gradient(135deg, rgb(255 196 114), rgb(255 108 99))" },
  { name: "青涩男孩", language: "中英文", gender: "男", description: "青涩稚嫩，真诚率直", gradient: "linear-gradient(135deg, rgb(250 202 241), rgb(255 111 73))" },
  { name: "雅知清声", language: "中英文", gender: "女", description: "优雅知性，清晰明快", gradient: "linear-gradient(135deg, rgb(109 218 194), rgb(255 180 94))" },
  { name: "慧海男声", language: "中英文", gender: "男", description: "睿智沉稳，学识渊博", gradient: "linear-gradient(135deg, rgb(99 116 247), rgb(103 215 221))" },
  { name: "黛玉柔声", language: "中英文", gender: "女", description: "轻柔纤细，温婉多思", gradient: "linear-gradient(135deg, rgb(255 123 91), rgb(245 187 244))" },
  { name: "日语女孩", language: "日文", gender: "女", description: "温柔甜美，日式清新", gradient: "linear-gradient(135deg, rgb(255 116 133), rgb(252 239 241))" },
  { name: "天真女童", language: "中英文", gender: "女", description: "稚嫩清脆，天真无邪", gradient: "linear-gradient(135deg, rgb(87 231 205), rgb(63 129 218))" },
  { name: "智慧男孩", language: "中英文", gender: "男", description: "朝气明亮，活力满满", gradient: "linear-gradient(135deg, rgb(69 135 224), rgb(225 243 255))" },
  { name: "lauren", language: "英文", gender: "女", description: "俏皮美音，灵动活泼", gradient: "linear-gradient(135deg, rgb(255 188 99), rgb(246 114 93))" },
  { name: "元气甜妹", language: "中英文", gender: "女", description: "清甜灵动，元气满格", gradient: "linear-gradient(135deg, rgb(106 186 236), rgb(225 240 252))" },
  { name: "播音男孩", language: "中英文", gender: "男", description: "字正腔圆，播音质感", gradient: "linear-gradient(135deg, rgb(113 205 244), rgb(108 89 235))" },
  { name: "体育女主播", language: "中英文", gender: "女", description: "活泼有趣，氛围担当", gradient: "linear-gradient(135deg, rgb(255 187 96), rgb(245 109 91))" },
  { name: "贴心女友", language: "中英文", gender: "女", description: "温柔细腻，贴心共情", gradient: "linear-gradient(135deg, rgb(104 180 234), rgb(45 119 222))" },
  { name: "暖心菲菲", language: "中英文", gender: "女", description: "温暖治愈，轻柔抚慰", gradient: "linear-gradient(135deg, rgb(255 182 94), rgb(255 116 100))" },
  { name: "Daniel", language: "英文", gender: "男", description: "沉稳美音，成熟从容", gradient: "linear-gradient(135deg, rgb(106 185 240), rgb(39 118 218))" },
  { name: "热场小甜椒", language: "中英文", gender: "女", description: "甜嗓控场，热梗连发", gradient: "linear-gradient(135deg, rgb(241 217 64), rgb(255 122 149))" },
];

const officialVoiceCards: VoiceCard[] = [
  ...voiceCards,
  { name: "风情女友", language: "中英文", gender: "女", description: "风情温婉，甜蜜亲昵", gradient: "linear-gradient(135deg, rgb(152 215 249), rgb(67 132 228))" },
  { name: "磁性哥哥", language: "中英文", gender: "男", description: "磁性低沉，沉稳可靠", gradient: "linear-gradient(135deg, rgb(97 180 236), rgb(42 113 213))" },
  { name: "Cindy", language: "英文", gender: "女", description: "美式甜嗓，青春明快", gradient: "linear-gradient(135deg, rgb(98 173 238), rgb(65 125 230))" },
  { name: "宠溺弟弟", language: "中英文", gender: "男", description: "宠溺奶音，活力满满", gradient: "linear-gradient(135deg, rgb(255 204 246), rgb(255 111 93))" },
  { name: "顽皮小男童", language: "中英文", gender: "男", description: "顽皮稚嫩，童真清澈", gradient: "linear-gradient(135deg, rgb(255 207 246), rgb(255 115 83))" },
  { name: "萝莉小女宝", language: "中英文", gender: "女", description: "萝莉奶萌，软甜可爱", gradient: "linear-gradient(135deg, rgb(244 222 71), rgb(255 131 153))" },
  { name: "懂懂乖乖女", language: "中英文", gender: "女", description: "懂懂纯真，青涩温柔", gradient: "linear-gradient(135deg, rgb(255 190 103), rgb(255 120 83))" },
  { name: "东北老铁", language: "中英文", gender: "男", description: "东北豪爽，唠嗑实诚", gradient: "linear-gradient(135deg, rgb(112 139 255), rgb(150 125 245))" },
  { name: "粤语姐姐", language: "中英文", gender: "女", description: "粤语温婉，随性活泼", gradient: "linear-gradient(135deg, rgb(140 216 247), rgb(62 132 223))" },
  { name: "古代诗仙", language: "中英文", gender: "男", description: "嗓音诗意，古韵悠长", gradient: "linear-gradient(135deg, rgb(255 196 236), rgb(255 129 98))" },
  { name: "Emily", language: "英文", gender: "女", description: "温柔美腔，优雅治愈", gradient: "linear-gradient(135deg, rgb(111 220 195), rgb(255 190 105))" },
  { name: "日本男生", language: "日文", gender: "男", description: "阳光开朗，日式活力", gradient: "linear-gradient(135deg, rgb(87 225 200), rgb(60 128 224))" },
  { name: "韩系姐妹", language: "韩文", gender: "女", description: "甜美俏皮，韩范十足", gradient: "linear-gradient(135deg, rgb(88 224 201), rgb(77 130 224))" },
  { name: "Magic Boy", language: "英文", gender: "男", description: "美式腔调，魔法男孩", gradient: "linear-gradient(135deg, rgb(242 210 89), rgb(93 212 203))" },
];

const videoCards = [
  { title: "未命名视频", time: "更新于 15:46:53", avatar: avatarCards[1]! },
  { title: "未命名视频", time: "更新于 15:44:28", avatar: avatarCards[9]! },
];

function AvatarConsolePage({ onOpenMore }: AvatarConsolePageProps) {
  const [activeView, setActiveView] = useState<ConsoleView>("voices");
  const [createOpen, setCreateOpen] = useState(false);
  const [authOpen, setAuthOpen] = useState(false);
  const [createRatio, setCreateRatio] = useState<BroadcastRatio>("16:9");
  const [editorRatio, setEditorRatio] = useState<BroadcastRatio | null>(null);
  const activeLabel = useMemo(() => findNavItem(activeView)?.label ?? "探索", [activeView]);
  const openCreateModal = () => {
    setCreateRatio("16:9");
    setCreateOpen(true);
  };
  const createBroadcast = () => {
    setCreateOpen(false);
    setEditorRatio(createRatio);
  };

  if (editorRatio) {
    return <BroadcastEditor ratio={editorRatio} onBack={() => setEditorRatio(null)} />;
  }

  return (
    <section className="avatar-console-page" aria-label="数字人控制台">
      <aside className="avatar-console-sidebar" aria-label="数字人工作台导航">
        <button type="button" className="avatar-console-brand" onClick={onOpenMore}>
          <span className="avatar-console-brand__mark">
            <DeploymentUnitOutlined />
          </span>
          <strong>数字人工作台</strong>
        </button>

        <button type="button" className="avatar-console-create is-active" onClick={openCreateModal}>
          <StarFilled />
          <span>视频创作</span>
        </button>

        <nav className="avatar-console-nav">
          {quickNav.map((item) => (
            <button
              key={item.key}
              type="button"
              className={activeView === item.key ? "is-selected" : ""}
              onClick={() => setActiveView(item.key)}
            >
              {item.icon}
              <span>{item.label}</span>
            </button>
          ))}
        </nav>

        <div className="avatar-console-nav-group">
          <span>数字人产品</span>
          <nav className="avatar-console-nav">
            {productNav.map((item) => (
              <button
                key={item.key}
                type="button"
                className={activeView === item.key ? "is-selected" : ""}
                onClick={() => setActiveView(item.key)}
              >
                {item.icon}
                <span>{item.label}</span>
              </button>
            ))}
          </nav>
        </div>

        <div className="avatar-console-nav-group">
          <span>数字人资产</span>
          <nav className="avatar-console-nav">
            {assetNav.map((item) => (
              <button
                key={item.key}
                type="button"
                className={activeView === item.key ? "is-selected" : ""}
                onClick={() => setActiveView(item.key)}
              >
                {item.icon}
                <span>{item.label}</span>
              </button>
            ))}
          </nav>
        </div>

        <button type="button" className="avatar-console-api">
          <ApiOutlined />
          <span>API服务</span>
        </button>
      </aside>

      <main className="avatar-console-main">
        <div className="avatar-console-scroll">
          {activeView === "explore" ? <ExploreView avatars={avatarCards} onCreate={openCreateModal} /> : null}
          {activeView === "videos" ? <VideosView videos={videoCards} onCreate={openCreateModal} /> : null}
          {activeView === "chat" ? <ChatView avatars={avatarCards.slice(0, 9)} onCreate={openCreateModal} /> : null}
          {activeView === "live" ? <LiveView onCreate={openCreateModal} onOpenAuthorization={() => setAuthOpen(true)} /> : null}
          {activeView === "avatars" ? <AvatarsView /> : null}
          {activeView === "voices" ? <VoicesView voices={voiceCards} /> : null}
        </div>

        <footer className="avatar-console-foot">
          <span>{activeLabel}中的内容均为本地预览数据，其准确性和完整性无法保证，不代表我们的态度或观点</span>
          <i />
          <span>浙公网安备 33010602009975号</span>
          <span>浙B2-20080101-4</span>
        </footer>
      </main>
      {createOpen ? (
        <CreateBroadcastModal
          ratio={createRatio}
          onRatioChange={setCreateRatio}
          onClose={() => setCreateOpen(false)}
          onCreate={createBroadcast}
        />
      ) : null}
      {authOpen ? <LiveAuthorizationModal onClose={() => setAuthOpen(false)} /> : null}
    </section>
  );
}

function ExploreView({ avatars, onCreate }: { avatars: AvatarCard[]; onCreate: () => void }) {
  return (
    <section className="avatar-console-view avatar-console-view--explore">
      <div className="avatar-console-explore-hero">
        <div>
          <h1>欢迎使用万相数字人</h1>
          <p>快速实现你的数字人创作灵感，为你打造专业的数字人视频。</p>
          <button type="button" onClick={onCreate}>
            <PlayCircleOutlined />
            立即创建
          </button>
        </div>
        <div className="avatar-console-hero-person">
          <AvatarPortrait avatar={avatars[10]!} size="large" />
          <span className="avatar-console-hero-bubble avatar-console-hero-bubble--yellow">万相数字人视频播报</span>
          <span className="avatar-console-hero-bubble avatar-console-hero-bubble--white">大家好，欢迎使用...</span>
          <span className="avatar-console-hero-bubble avatar-console-hero-bubble--blue">灿烂阳光.mp3</span>
        </div>
      </div>
      <CatalogHeader title="从你喜欢的数字人形象开始" />
      <AvatarMosaic avatars={avatars.concat(avatars).slice(0, 30)} />
    </section>
  );
}

function VideosView({ videos, onCreate }: { videos: typeof videoCards; onCreate: () => void }) {
  return (
    <section className="avatar-console-view avatar-console-view--videos">
      <div className="avatar-console-video-hero">
        <div>
          <h1>即刻开始，创建播报视频</h1>
          <p>仅需一张照片即可开启创作之旅</p>
          <button type="button" onClick={onCreate}>
            <StarFilled />
            立即创建
          </button>
        </div>
        <div className="avatar-console-video-showcase">
          <AvatarPortrait avatar={avatarCards[9]!} size="large" />
          <AvatarPortrait avatar={avatarCards[4]!} size="small" />
          <AvatarPortrait avatar={avatarCards[6]!} size="small" />
          <AvatarPortrait avatar={avatarCards[7]!} size="tiny" />
        </div>
      </div>

      <div className="avatar-console-list-head">
        <h2>我的视频</h2>
        <div>
          <label>
            <SearchOutlined />
            <input placeholder="请输入名称" />
          </label>
          <button type="button">
            <PlayCircleOutlined />
            生成记录
          </button>
        </div>
      </div>

      <div className="avatar-console-video-grid">
        {videos.map((video) => (
          <article key={`${video.title}-${video.time}`} className="avatar-console-video-card">
            <div>
              <AvatarPortrait avatar={video.avatar} size="card" />
            </div>
            <strong>{video.title}</strong>
            <span>草稿</span>
            <p>{video.time}</p>
          </article>
        ))}
      </div>
    </section>
  );
}

function ChatView({ avatars, onCreate }: { avatars: AvatarCard[]; onCreate: () => void }) {
  return (
    <section className="avatar-console-view avatar-console-view--chat">
      <div className="avatar-console-chat-hero">
        <div>
          <h1>来和你的数字人聊聊吧</h1>
          <p>适配多样业务场景，创建全天候可对话数字人</p>
          <button type="button" onClick={onCreate}>
            <StarFilled />
            立即创建
          </button>
        </div>
        <div className="avatar-console-chat-stack">
          <AvatarPortrait avatar={avatars[2]!} size="medium" />
          <AvatarPortrait avatar={avatars[5]!} size="medium" />
        </div>
      </div>
      <CatalogHeader title="官方形象" secondary="我创建的" />
      <AvatarShelf avatars={avatars} />
    </section>
  );
}

function LiveView({ onCreate, onOpenAuthorization }: { onCreate: () => void; onOpenAuthorization: () => void }) {
  return (
    <section className="avatar-console-view avatar-console-view--live">
      <div className="avatar-console-live-hero">
        <div>
          <h1>欢迎体验数字人直播间</h1>
          <p>支持电商直播场景的数字人主播推流，实现7*24小时无人直播</p>
          <div>
            <button type="button" onClick={onCreate}>
              <StarFilled />
              开通服务
            </button>
            <button type="button" onClick={onOpenAuthorization}>直播平台授权开通</button>
          </div>
        </div>
        <div className="avatar-console-live-stage">
          <div className="avatar-console-live-window">
            <span />
            <span />
            <span />
            <AvatarPortrait avatar={avatarCards[10]!} size="broadcast" />
            <em>Live</em>
            <strong>3.2K</strong>
          </div>
          <div className="avatar-console-live-card avatar-console-live-card--script">
            <b>脚本润色</b>
            <p>今天给大家带来的这支「雅韵」唇膏，是品牌沉淀多年的经典款。</p>
          </div>
          <div className="avatar-console-live-card avatar-console-live-card--room">
            <b>灵活搭建直播间</b>
            <div>
              <span />
              <span />
              <span />
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function LiveAuthorizationModal({ onClose }: { onClose: () => void }) {
  return (
    <div className="avatar-auth-modal" role="dialog" aria-modal="true" aria-labelledby="avatar-auth-title">
      <button type="button" className="avatar-auth-modal__backdrop" aria-label="关闭授权管理" onClick={onClose} />
      <section className="avatar-auth-modal__panel">
        <header className="avatar-auth-modal__head">
          <h2 id="avatar-auth-title">授权管理</h2>
          <button type="button" aria-label="关闭" onClick={onClose}>
            <CloseOutlined />
          </button>
        </header>
        <div className="avatar-auth-modal__body">
          <div className="avatar-auth-modal__table-head" role="row">
            <span role="columnheader">直播账号</span>
            <span role="columnheader">授权平台</span>
            <span role="columnheader">状态</span>
            <span role="columnheader">操作</span>
          </div>
          <div className="avatar-auth-modal__empty" role="status">
            <InboxOutlined />
            <span>暂无数据</span>
          </div>
        </div>
        <footer className="avatar-auth-modal__foot">
          <button type="button">
            <PlusOutlined />
            新增授权
          </button>
        </footer>
      </section>
    </div>
  );
}

function CreateBroadcastModal({
  ratio,
  onRatioChange,
  onClose,
  onCreate,
}: {
  ratio: BroadcastRatio;
  onRatioChange: (ratio: BroadcastRatio) => void;
  onClose: () => void;
  onCreate: () => void;
}) {
  return (
    <div className="avatar-create-modal" role="dialog" aria-modal="true" aria-labelledby="avatar-create-title">
      <section className="avatar-create-modal__panel">
        <button type="button" className="avatar-create-modal__close" aria-label="关闭" onClick={onClose}>
          <CloseOutlined />
        </button>
        <div className="avatar-create-modal__head">
          <h2 id="avatar-create-title">创建播报视频</h2>
          <p>选择你想创建的视频比例</p>
        </div>
        <div className="avatar-create-modal__options">
          <button
            type="button"
            className={`avatar-create-ratio-card${ratio === "16:9" ? " is-selected" : ""}`}
            onClick={() => onRatioChange("16:9")}
          >
            <span className="avatar-create-ratio-card__preview avatar-create-ratio-card__preview--wide">
              <i />
              <em>16:9</em>
              <PlayCircleOutlined />
            </span>
            <strong>横版&nbsp; 16:9</strong>
          </button>
          <button
            type="button"
            className={`avatar-create-ratio-card${ratio === "9:16" ? " is-selected" : ""}`}
            onClick={() => onRatioChange("9:16")}
          >
            <span className="avatar-create-ratio-card__preview avatar-create-ratio-card__preview--tall">
              <i />
              <em>9:16</em>
              <PlayCircleOutlined />
            </span>
            <strong>竖版&nbsp; 9:16</strong>
          </button>
        </div>
        <button type="button" className="avatar-create-modal__submit" onClick={onCreate}>
          立即创建
        </button>
      </section>
    </div>
  );
}

function BroadcastEditor({ ratio, onBack }: { ratio: BroadcastRatio; onBack: () => void }) {
  const isPortrait = ratio === "9:16";
  const actor = isPortrait ? avatarCards[8]! : avatarCards[7]!;
  const [activeTool, setActiveTool] = useState<EditorTool>("content");
  const [projectName, setProjectName] = useState("未命名视频");
  const [nameDraft, setNameDraft] = useState("未命名视频");
  const [editingName, setEditingName] = useState(false);
  const [layers, setLayers] = useState<AvatarEditorLayer[]>(() => createDefaultAvatarEditorLayers(ratio));
  const [activeLayerId, setActiveLayerId] = useState<AvatarEditorLayerId | null>(null);
  const [layersOpen, setLayersOpen] = useState(false);
  const sceneRef = useRef<HTMLDivElement | null>(null);
  const dragStateRef = useRef<{
    layerId: AvatarEditorLayerId;
    offsetX: number;
    offsetY: number;
  } | null>(null);
  const orderedLayers = useMemo(() => [...layers].sort((a, b) => a.zIndex - b.zIndex), [layers]);
  const layerStack = useMemo(() => [...orderedLayers].reverse(), [orderedLayers]);
  const activeLayer = activeLayerId ? layers.find((layer) => layer.id === activeLayerId) : undefined;
  const selectedCanvasLayer = activeLayer?.id === "avatar" || activeLayer?.id === "sticker" ? activeLayer : undefined;

  const startEditingName = () => {
    setNameDraft(projectName);
    setEditingName(true);
  };

  const saveProjectName = () => {
    const nextName = nameDraft.trim() || "未命名视频";
    setProjectName(nextName);
    setNameDraft(nextName);
    setEditingName(false);
  };

  const cancelProjectNameEdit = () => {
    setNameDraft(projectName);
    setEditingName(false);
  };

  const selectLayer = (layer: AvatarEditorLayer) => {
    setActiveLayerId(layer.id);
    setActiveTool(layer.tool);
  };

  const layerStyle = (layer: AvatarEditorLayer): CSSProperties => ({
    left: `${layer.x}%`,
    top: `${layer.y}%`,
    width: `${layer.width}%`,
    height: `${layer.height}%`,
    zIndex: layer.zIndex,
  });

  const pointFromEvent = (event: PointerEvent<HTMLElement>) => {
    const scene = sceneRef.current;
    if (!scene) return null;
    const rect = scene.getBoundingClientRect();
    if (!rect.width || !rect.height) return null;
    return {
      x: ((event.clientX - rect.left) / rect.width) * 100,
      y: ((event.clientY - rect.top) / rect.height) * 100,
    };
  };

  const handleLayerPointerDown = (event: PointerEvent<HTMLElement>, layer: AvatarEditorLayer) => {
    event.stopPropagation();
    selectLayer(layer);
    if (layer.locked) return;
    const point = pointFromEvent(event);
    if (!point) return;
    dragStateRef.current = {
      layerId: layer.id,
      offsetX: point.x - layer.x,
      offsetY: point.y - layer.y,
    };
    event.currentTarget.setPointerCapture(event.pointerId);
  };

  const handleLayerPointerMove = (event: PointerEvent<HTMLElement>) => {
    const drag = dragStateRef.current;
    if (!drag) return;
    const point = pointFromEvent(event);
    if (!point) return;
    setLayers((current) =>
      moveAvatarEditorLayer(current, drag.layerId, {
        x: point.x - drag.offsetX,
        y: point.y - drag.offsetY,
      }),
    );
  };

  const endLayerDrag = (event: PointerEvent<HTMLElement>) => {
    dragStateRef.current = null;
    if (event.currentTarget.hasPointerCapture(event.pointerId)) {
      event.currentTarget.releasePointerCapture(event.pointerId);
    }
  };

  const renderCanvasLayer = (layer: AvatarEditorLayer) => {
    if (layer.id === "solidBackground" || layer.id === "background") {
      return (
        <div
          key={layer.id}
          className={`avatar-editor-scene-layer avatar-editor-scene-layer--${layer.id}`}
          style={layerStyle(layer)}
          aria-hidden="true"
        >
          {layer.id === "background" ? (
            <>
              <div className="avatar-editor-wall-line" />
              <div className="avatar-editor-floor" />
              {isPortrait ? (
                <div className="avatar-editor-nursery" />
              ) : (
                <>
                  <div className="avatar-editor-plant" />
                  <div className="avatar-editor-studio-vase avatar-editor-studio-vase--large" />
                  <div className="avatar-editor-studio-vase avatar-editor-studio-vase--small" />
                  <div className="avatar-editor-canvas-watermark">AI生成</div>
                </>
              )}
            </>
          ) : null}
        </div>
      );
    }

    const isSelected = selectedCanvasLayer?.id === layer.id;
    return (
      <div
        key={layer.id}
        role="button"
        tabIndex={0}
        className={`avatar-editor-canvas-layer avatar-editor-canvas-layer--${layer.id}${isSelected ? " is-selected" : ""}`}
        style={layerStyle(layer)}
        aria-label={`${layer.label} 图层`}
        onPointerDown={(event) => handleLayerPointerDown(event, layer)}
        onPointerMove={handleLayerPointerMove}
        onPointerUp={endLayerDrag}
        onPointerCancel={endLayerDrag}
        onKeyDown={(event) => {
          if (event.key !== "Enter" && event.key !== " ") return;
          event.preventDefault();
          selectLayer(layer);
        }}
      >
        {layer.id === "avatar" ? <EditorAvatarFigure compact={false} /> : null}
        {layer.id === "sticker" ? <span className="avatar-editor-sticker-shape" /> : null}
        <em>{layer.label}</em>
        {isSelected ? (
          <div
            className="avatar-editor-selection-toolbar"
            aria-label="选中图层操作"
            onPointerDown={(event) => event.stopPropagation()}
            onClick={(event) => event.stopPropagation()}
          >
            <button type="button" onClick={() => setLayersOpen(true)}>
              <BlockOutlined />
              图层
            </button>
            <button type="button">
              <DeploymentUnitOutlined />
              应用到全局
            </button>
          </div>
        ) : null}
      </div>
    );
  };

  return (
    <section className="avatar-editor-page" aria-label={`${ratio}播报视频编辑器`}>
      <header className="avatar-editor-topbar">
        <div className="avatar-editor-title">
          <button type="button" aria-label="返回" onClick={onBack}>
            <ArrowLeftOutlined />
          </button>
          {editingName ? (
            <input
              className="avatar-editor-title__input"
              value={nameDraft}
              maxLength={40}
              autoFocus
              aria-label="编辑项目名称"
              onFocus={(event) => event.currentTarget.select()}
              onChange={(event) => setNameDraft(event.target.value)}
              onBlur={saveProjectName}
              onKeyDown={(event) => {
                if (event.key === "Enter") {
                  event.preventDefault();
                  saveProjectName();
                }
                if (event.key === "Escape") {
                  event.preventDefault();
                  cancelProjectNameEdit();
                }
              }}
            />
          ) : (
            <button type="button" className="avatar-editor-title__name-button" aria-label="编辑项目名称" onClick={startEditingName}>
              <strong>{projectName}</strong>
              <EditOutlined />
            </button>
          )}
          <span>已自动保存</span>
        </div>
        <div className="avatar-editor-actions">
          <button type="button">
            <HistoryOutlined />
            生成记录
          </button>
          <button type="button">生成视频</button>
        </div>
      </header>

      <main className="avatar-editor-workspace">
        <nav className="avatar-editor-rail" aria-label="编辑工具">
          {editorTools.map((tool) => (
            <button
              key={tool.key}
              type="button"
              className={activeTool === tool.key ? "is-active" : ""}
              aria-pressed={activeTool === tool.key}
              onClick={() => setActiveTool(tool.key)}
            >
              {tool.icon}
              <span>{tool.label}</span>
            </button>
          ))}
        </nav>

        <EditorInspector activeTool={activeTool} actor={actor} isPortrait={isPortrait} />

        <section className="avatar-editor-stage">
          <div className="avatar-editor-undo">
            <button type="button">↶</button>
            <button type="button">↷</button>
          </div>
          <button
            type="button"
            className={`avatar-editor-layer${layersOpen ? " is-active" : ""}`}
            aria-expanded={layersOpen}
            aria-label="图层"
            onClick={() => setLayersOpen((open) => !open)}
          >
            <BlockOutlined />
          </button>
          {layersOpen ? (
            <aside className="avatar-editor-layer-panel" aria-label="图层面板">
              <div className="avatar-editor-layer-panel__head">
                <strong>图层</strong>
                <span>{activeLayer?.label}</span>
              </div>
              <div className="avatar-editor-layer-panel__list">
                {layerStack.map((layer) => (
                  <button
                    key={layer.id}
                    type="button"
                    className={`avatar-editor-layer-row${activeLayerId === layer.id ? " is-selected" : ""}`}
                    onClick={() => selectLayer(layer)}
                  >
                    <span>{layer.label}</span>
                    <em>{layer.locked ? "锁定" : `Z ${layer.zIndex}`}</em>
                  </button>
                ))}
              </div>
              <div className="avatar-editor-layer-panel__actions">
                <button
                  type="button"
                  onClick={() => {
                    if (!activeLayerId) return;
                    setLayers((current) => bringAvatarEditorLayerForward(current, activeLayerId));
                  }}
                  disabled={!activeLayerId || activeLayer?.locked}
                >
                  上移
                </button>
                <button
                  type="button"
                  onClick={() => {
                    if (!activeLayerId) return;
                    setLayers((current) => sendAvatarEditorLayerBackward(current, activeLayerId));
                  }}
                  disabled={!activeLayerId || activeLayer?.locked}
                >
                  下移
                </button>
              </div>
            </aside>
          ) : null}
          <div className={`avatar-editor-canvas avatar-editor-canvas--${isPortrait ? "portrait" : "landscape"}`}>
            <div
              ref={sceneRef}
              className="avatar-editor-scene"
              onPointerDown={(event) => {
                if (event.target !== event.currentTarget) return;
                setActiveLayerId(null);
              }}
            >
              {orderedLayers.map(renderCanvasLayer)}
            </div>
          </div>
          {activeLayer ? (
            <div className="avatar-editor-selection-readout">
              <strong>{activeLayer.label}</strong>
              <span>{`X ${Math.round(activeLayer.x)} · Y ${Math.round(activeLayer.y)} · Z ${activeLayer.zIndex}`}</span>
            </div>
          ) : null}
        </section>
      </main>

      <footer className="avatar-editor-timeline">
        <div className="avatar-editor-play">
          <button type="button">
            <PlayCircleOutlined />
          </button>
          <span>00:00 / 00:00</span>
        </div>
        <div className={`avatar-editor-clip avatar-editor-clip--${isPortrait ? "portrait" : "landscape"}`}>
          <b>1</b>
          <div>
            {isPortrait ? <AvatarPortrait avatar={actor} size="clip" /> : <EditorClipPreview />}
            <em>0.00s</em>
          </div>
          <button type="button" aria-label="更多">
            <EllipsisOutlined />
          </button>
        </div>
        <button type="button" className="avatar-editor-add">
          <PlusOutlined />
        </button>
      </footer>
    </section>
  );
}

function EditorAvatarFigure({ compact }: { compact: boolean }) {
  return (
    <div className={`avatar-editor-figure${compact ? " avatar-editor-figure--compact" : ""}`} aria-hidden="true">
      <span className="avatar-editor-figure__hair" />
      <span className="avatar-editor-figure__head" />
      <span className="avatar-editor-figure__neck" />
      <span className="avatar-editor-figure__torso" />
      <span className="avatar-editor-figure__pattern avatar-editor-figure__pattern--upper" />
      <span className="avatar-editor-figure__pattern avatar-editor-figure__pattern--lower" />
      <span className="avatar-editor-figure__skirt" />
      <span className="avatar-editor-figure__arm avatar-editor-figure__arm--left" />
      <span className="avatar-editor-figure__arm avatar-editor-figure__arm--right" />
      <span className="avatar-editor-figure__leg avatar-editor-figure__leg--left" />
      <span className="avatar-editor-figure__leg avatar-editor-figure__leg--right" />
    </div>
  );
}

function EditorClipPreview() {
  return (
    <span className="avatar-editor-clip-preview" aria-hidden="true">
      <span className="avatar-editor-clip-plant" />
      <span className="avatar-editor-clip-hat" />
      <EditorAvatarFigure compact />
    </span>
  );
}

function EditorInspector({
  activeTool,
  actor,
  isPortrait,
}: {
  activeTool: EditorTool;
  actor: AvatarCard;
  isPortrait: boolean;
}) {
  const speakerName = isPortrait ? "天真女童" : "日语女孩";

  if (activeTool === "content") {
    return (
      <aside className="avatar-editor-script avatar-editor-inspector">
        <div className="avatar-editor-script__head">
          <h2>播报内容</h2>
          <SettingOutlined />
        </div>
        <div className="avatar-editor-speaker">
          <b>1</b>
          <span />
          <strong>{speakerName}</strong>
          <PlayCircleOutlined />
          <button type="button" aria-label="更多">
            <EllipsisOutlined />
          </button>
        </div>
        <textarea placeholder="点击输入内容" maxLength={800} />
        <div className="avatar-editor-script__count">0/800</div>
        <div className="avatar-editor-script__tools">
          <button type="button">+ 片段</button>
          <button type="button">音频</button>
        </div>
      </aside>
    );
  }

  if (activeTool === "avatar") {
    return (
      <aside className="avatar-editor-script avatar-editor-inspector">
        <div className="avatar-editor-picker-head">
          <h2>形象选择</h2>
          <button type="button">
            公共形象
            <DownOutlined />
          </button>
        </div>
        <label className="avatar-editor-search-field">
          <SearchOutlined />
          <input placeholder="请输入名称" />
        </label>
        <div className="avatar-editor-avatar-pick-grid">
          {[actor, ...avatarCards, ...avatarCards.slice(0, 8)].slice(0, 21).map((avatar, index) => (
            <button
              key={`${avatar.name}-${index}`}
              type="button"
              className={`avatar-editor-avatar-pick${index === 0 ? " is-selected" : ""}`}
              aria-label={avatar.name}
            >
              <AvatarPortrait avatar={avatar} size="mosaic" />
              {index === 0 ? <i /> : null}
            </button>
          ))}
        </div>
      </aside>
    );
  }

  if (activeTool === "subtitle") {
    return (
      <aside className="avatar-editor-script avatar-editor-inspector">
        <div className="avatar-editor-picker-head">
          <div className="avatar-editor-subtitle-switch">
            <h2>字幕设置</h2>
            <label>
              <input type="checkbox" />
              <span />
              字幕关
            </label>
          </div>
          <button type="button">
            官方样式
            <DownOutlined />
          </button>
        </div>
        <div className="avatar-editor-subtitle-grid">
          {["blue", "orange", "pill", "underline", "solid", "black"].map((styleName) => (
            <button key={styleName} type="button" className={`avatar-editor-subtitle-style is-${styleName}`}>
              <span>欢迎使用数字人</span>
            </button>
          ))}
        </div>
      </aside>
    );
  }

  if (activeTool === "background") {
    return (
      <aside className="avatar-editor-script avatar-editor-inspector">
        <div className="avatar-editor-picker-head">
          <h2>背景选择</h2>
          <button type="button">
            图片背景
            <DownOutlined />
          </button>
        </div>
        <div className="avatar-editor-background-palette">
          {Array.from({ length: 17 }).map((_, index) => (
            <button
              key={index}
              type="button"
              className={`avatar-editor-background-tile bg-${index + 1}${index === 10 ? " is-selected" : ""}`}
              aria-label={`背景 ${index + 1}`}
            >
              <span />
              {index === 10 ? <i /> : null}
            </button>
          ))}
        </div>
      </aside>
    );
  }

  return (
    <aside className="avatar-editor-script avatar-editor-inspector">
      <div className="avatar-editor-picker-head">
        <h2>贴图选择</h2>
        <button type="button">
          官方素材
          <DownOutlined />
        </button>
      </div>
      <label className="avatar-editor-search-field">
        <SearchOutlined />
        <input placeholder="搜索贴图素材" />
      </label>
      <div className="avatar-editor-sticker-grid">
        {["flower", "cone", "globe", "headset", "board", "cap", "desk", "chart"].map((name) => (
          <button key={name} type="button" className="avatar-editor-sticker-card" aria-label={name}>
            <span className={`avatar-editor-sticker-visual is-${name}`}>
              <i />
              <i />
              <i />
            </span>
          </button>
        ))}
      </div>
    </aside>
  );
}

function AvatarsView() {
  const [trainingOpen, setTrainingOpen] = useState(false);

  return (
    <section className="avatar-console-view avatar-console-view--avatars">
      <PageTitle title="形象库" tabs={["我创建的", "官方形象"]} activeTab="我创建的" />
      <CatalogHeader title="我的数字人" compact info />
      <button type="button" className="avatar-console-create-card" onClick={() => setTrainingOpen(true)}>
        <PlusOutlined />
        <span>创建数字人</span>
      </button>
      <CatalogHeader title="我的形象" compact filters info />
      <div className="avatar-console-empty-state avatar-console-empty-state--avatar" role="status">
        <div>
          <CustomerServiceOutlined />
        </div>
        <strong>暂无形象</strong>
      </div>
      {trainingOpen ? <AvatarTrainingModal onClose={() => setTrainingOpen(false)} /> : null}
    </section>
  );
}

function AvatarTrainingModal({ onClose }: { onClose: () => void }) {
  const [draft, setDraft] = useState<AvatarTrainingDraft>(() => createAvatarTrainingDraft());
  const selectedScenario = avatarTrainingScenarios.find((scenario) => scenario.key === draft.selectedScenario);
  const selectScenario = (scenario: AvatarTrainingScenarioKey) => {
    setDraft((current) => selectAvatarTrainingScenario(current, scenario));
  };

  return (
    <div className="avatar-training-modal" role="dialog" aria-modal="true" aria-labelledby="avatar-training-title">
      <section className="avatar-training-modal__panel">
        <button type="button" className="avatar-training-modal__close" aria-label="关闭" onClick={onClose}>
          <CloseOutlined />
        </button>

        {draft.step === "scenario" ? (
          <>
            <div className="avatar-training-modal__head">
              <h2 id="avatar-training-title">训练专属数字人</h2>
              <p>选择你想应用的数字人场景</p>
            </div>
            <div className="avatar-training-scenarios">
              {avatarTrainingScenarios.map((scenario) => (
                <button
                  key={scenario.key}
                  type="button"
                  className={`avatar-training-scenario avatar-training-scenario--${scenario.key}${draft.selectedScenario === scenario.key ? " is-selected" : ""}`}
                  aria-pressed={draft.selectedScenario === scenario.key}
                  onClick={() => selectScenario(scenario.key)}
                >
                  <span className="avatar-training-scenario__visual" aria-hidden="true">
                    <i />
                    <b />
                    <em />
                  </span>
                  <strong>{scenario.label}</strong>
                  <span>{scenario.description}</span>
                </button>
              ))}
            </div>
            <div className="avatar-training-modal__actions">
              <button
                type="button"
                disabled={!draft.canContinue}
                onClick={() => setDraft((current) => continueAvatarTraining(current))}
              >
                下一步
              </button>
            </div>
          </>
        ) : (
          <>
            <div className="avatar-training-modal__head">
              <h2 id="avatar-training-title">上传训练素材</h2>
              <p>{selectedScenario ? `已选择「${selectedScenario.label}」场景，继续补充数字人素材。` : "继续补充数字人素材。"}</p>
            </div>
            <div className="avatar-training-next-step">
              <div className="avatar-training-upload">
                <PlusOutlined />
                <strong>上传人物素材</strong>
                <span>支持正面半身、全身或清晰肖像图片</span>
              </div>
              <div className="avatar-training-guides">
                <strong>素材要求</strong>
                <span>单人出镜，面部清晰无遮挡</span>
                <span>光线均匀，背景简洁</span>
                <span>建议上传高清原图以提升训练效果</span>
              </div>
            </div>
            <div className="avatar-training-modal__actions">
              <button type="button" onClick={() => setDraft((current) => ({ ...current, step: "scenario" }))}>
                上一步
              </button>
              <button type="button" disabled>
                开始训练
              </button>
            </div>
          </>
        )}
      </section>
    </div>
  );
}

function VoicesView({ voices }: { voices: VoiceCard[] }) {
  const [activeTab, setActiveTab] = useState<VoiceLibraryTabKey>("official");
  const [cloneOpen, setCloneOpen] = useState(false);
  const cards = voices.length > officialVoiceCards.length ? voices : officialVoiceCards;
  const tabLabels = voiceLibraryTabs.map((tab) => tab.label);
  const activeTabLabel = voiceLibraryTabs.find((tab) => tab.key === activeTab)?.label ?? tabLabels[0]!;
  const handleVoiceTabChange = (label: string) => {
    const nextTab = voiceLibraryTabs.find((tab) => tab.label === label);
    if (nextTab) setActiveTab(nextTab.key);
  };

  return (
    <section className="avatar-console-view avatar-console-view--voices">
      <PageTitle title="声音库" tabs={tabLabels} activeTab={activeTabLabel} onTabChange={handleVoiceTabChange}>
        <button type="button" onClick={() => setCloneOpen(true)}>
          <PlusOutlined />
          创建音色
        </button>
      </PageTitle>
      {activeTab === "official" ? (
        <>
          <div className="avatar-console-filter-line avatar-console-filter-line--voices">
            <button type="button">
              性别
              <DownOutlined />
            </button>
            <button type="button">
              语言
              <DownOutlined />
            </button>
          </div>
          <div className="avatar-console-voice-grid">
            {cards.map((voice) => (
              <article key={voice.name} className="avatar-console-voice-card">
                <span style={{ background: voice.gradient }} />
                <button type="button" aria-label={`试听 ${voice.name}`}>
                  <PlayCircleOutlined />
                </button>
                <div>
                  <strong>{voice.name}</strong>
                  <em>{voice.language}</em>
                  <p>
                    {voice.gender === "男" ? "♂" : "♀"} {voice.description}
                  </p>
                </div>
              </article>
            ))}
          </div>
        </>
      ) : (
        <div className="avatar-console-empty-state avatar-console-empty-state--voice" role="status">
          <div>
            <SoundOutlined />
          </div>
          <strong>暂无声音</strong>
          <span>请先创建一个音色</span>
        </div>
      )}
      {cloneOpen ? <VoiceCloneModal onClose={() => setCloneOpen(false)} /> : null}
    </section>
  );
}

function PageTitle({
  title,
  tabs,
  activeTab,
  children,
  onTabChange,
}: {
  title: string;
  tabs: string[];
  activeTab: string;
  children?: ReactNode;
  onTabChange?: (tab: string) => void;
}) {
  return (
    <div className="avatar-console-titlebar">
      <div>
        <h1>{title}</h1>
        <nav>
          {tabs.map((tab) => (
            <button
              key={tab}
              type="button"
              className={tab === activeTab ? "is-current" : ""}
              onClick={() => onTabChange?.(tab)}
            >
              {tab}
            </button>
          ))}
        </nav>
      </div>
      {children}
    </div>
  );
}

function VoiceCloneModal({ onClose }: { onClose: () => void }) {
  const draft = useMemo(() => createVoiceCloneDraft(), []);
  const [targetLanguage, setTargetLanguage] = useState(draft.targetLanguage);
  const [languageOpen, setLanguageOpen] = useState(false);

  return (
    <div className="avatar-voice-clone" role="dialog" aria-modal="true" aria-labelledby="avatar-voice-clone-title">
      <section className="avatar-voice-clone__panel">
        <header className="avatar-voice-clone__head">
          <h2 id="avatar-voice-clone-title">声音克隆</h2>
          <button type="button" aria-label="关闭" onClick={onClose}>
            <CloseOutlined />
          </button>
        </header>
        <div className="avatar-voice-clone__body">
          <div className="avatar-voice-clone__form">
            <fieldset>
              <legend>音色</legend>
              <label>
                <input type="radio" name="voice-gender" defaultChecked={draft.gender === "male"} />
                男声
              </label>
              <label>
                <input type="radio" name="voice-gender" defaultChecked={draft.gender === "female"} />
                女声
              </label>
            </fieldset>
            <label className="avatar-voice-clone__input">
              <span>声音名称</span>
              <input placeholder="为你的声音命名" maxLength={draft.nameMaxLength} />
              <em>0 / {draft.nameMaxLength}</em>
            </label>
            <fieldset>
              <legend>克隆方式</legend>
              <label>
                <input type="radio" name="voice-mode" defaultChecked={draft.cloneMode === "record"} />
                录音
              </label>
              <label>
                <input type="radio" name="voice-mode" defaultChecked={draft.cloneMode === "upload"} />
                上传
              </label>
            </fieldset>
            <div className="avatar-voice-clone__select">
              <span>目标语种</span>
              <button
                type="button"
                aria-expanded={languageOpen}
                aria-haspopup="listbox"
                onClick={() => setLanguageOpen((open) => !open)}
              >
                {targetLanguage}
                <DownOutlined />
              </button>
              {languageOpen ? (
                <div className="avatar-voice-clone__language-list" role="listbox" aria-label="目标语种">
                  {voiceCloneLanguageOptions.map((language) => (
                    <button
                      key={language}
                      type="button"
                      className={language === targetLanguage ? "is-selected" : ""}
                      role="option"
                      aria-selected={language === targetLanguage}
                      onClick={() => {
                        setTargetLanguage(language);
                        setLanguageOpen(false);
                      }}
                    >
                      {language}
                    </button>
                  ))}
                </div>
              ) : null}
            </div>
            <div className="avatar-voice-clone__steps">
              <strong>声音克隆流程</strong>
              {["点击右侧录制按钮", "朗读右侧示例区的播报内容，并点击结束按钮", "点击开始克隆，等待约1分钟"].map((step, index) => (
                <div key={step} className={index === 0 ? "is-current" : ""}>
                  <b>{index + 1}</b>
                  <span>{step}</span>
                </div>
              ))}
            </div>
          </div>
          <div className="avatar-voice-clone__record">
            <div className="avatar-voice-clone__script">{VOICE_CLONE_SCRIPT}</div>
            <button type="button" className="avatar-voice-clone__refresh">
              换一换
              <span />
            </button>
            <button type="button" className="avatar-voice-clone__record-button" aria-label="开始录制" />
            <span>点击红点开始录制</span>
          </div>
        </div>
        <footer className="avatar-voice-clone__foot">
          <label>
            <input type="checkbox" />
            <span>我确认我拥有复制当前音频的版权和使用权，我保证不会用数字人做违法创作，并且严格遵守</span>
            <a href="#/avatarConsole">《通义智能产品服务协议》</a>
          </label>
          <div>
            <button type="button" onClick={onClose}>
              取消
            </button>
            <button type="button" disabled>
              开始克隆
            </button>
          </div>
        </footer>
      </section>
    </div>
  );
}

function CatalogHeader({
  title,
  secondary,
  compact,
  filters,
  info,
}: {
  title: string;
  secondary?: string;
  compact?: boolean;
  filters?: boolean;
  info?: boolean;
}) {
  return (
    <div className={`avatar-console-catalog-head${compact ? " is-compact" : ""}`}>
      <div>
        <h2>
          {title}
          {info ? <span>ⓘ</span> : null}
        </h2>
        {secondary ? <button type="button">{secondary}</button> : null}
      </div>
      {filters ? (
        <div className="avatar-console-catalog-filters">
          <button type="button">
            性别
            <DownOutlined />
          </button>
          <button type="button">
            类型
            <DownOutlined />
          </button>
          <button type="button">
            场景
            <DownOutlined />
          </button>
          <label>
            <SearchOutlined />
            <input placeholder="搜索数字人形象..." />
          </label>
        </div>
      ) : null}
    </div>
  );
}

function AvatarMosaic({ avatars }: { avatars: AvatarCard[] }) {
  return (
    <div className="avatar-console-mosaic">
      {avatars.map((avatar, index) => (
        <article key={`${avatar.name}-${index}`} className="avatar-console-mosaic-card">
          <AvatarPortrait avatar={avatar} size="mosaic" />
          {index === 14 ? (
            <div>
              <strong>{avatar.name}</strong>
              <span>{avatar.type}</span>
            </div>
          ) : null}
        </article>
      ))}
    </div>
  );
}

function AvatarShelf({ avatars }: { avatars: AvatarCard[] }) {
  return (
    <div className="avatar-console-avatar-shelf">
      {avatars.map((avatar) => (
        <article key={avatar.name}>
          <AvatarPortrait avatar={avatar} size="shelf" />
          <strong>{avatar.name}</strong>
          <span>{avatar.type}</span>
        </article>
      ))}
    </div>
  );
}

function AvatarPortrait({ avatar, size }: { avatar: AvatarCard; size: "tiny" | "small" | "medium" | "large" | "card" | "broadcast" | "mosaic" | "shelf" | "editor" | "clip" }) {
  return (
    <div className={`avatar-console-portrait avatar-console-portrait--${size}`} style={{ background: avatar.background }}>
      <div style={{ background: avatar.accent }} />
      <span />
      <span />
      <strong>{avatar.name.slice(0, 1)}</strong>
    </div>
  );
}

function findNavItem(view: ConsoleView) {
  return [...quickNav, ...productNav, ...assetNav].find((item) => item.key === view);
}

export default AvatarConsolePage;
