"use client";

import { useEffect, useRef, useState } from "react";

import { AppShell } from "@/components/AppShell";
import { Drawer } from "@/components/Drawer";
import { useToast } from "@/components/Toast";
import { StatusNote } from "@/components/ui/StatusNote";
import type { ProjectResponse } from "@/lib/api/types";
import { friendlyError } from "@/lib/errors/messages";
import { useAutosave } from "@/lib/autosave/useAutosave";
import { useDraftStream } from "@/lib/stream/useDraftStream";
import {
  WORKBENCH_CHAPTER_NO,
  type ChapterEntry,
} from "@/lib/workbench/chapter";
import { composeDirective } from "@/lib/workbench/directive";
import { applyRefinement } from "@/lib/workbench/refineApply";
import { ChapterList, ChapterListContent } from "./ChapterList";
import { ChapterAssistant, AssistantContent } from "./ChapterAssistant";
import { Editor, type EditorSelection } from "./Editor";
import { RefinePanel } from "./RefinePanel";
import { ContinuePanel } from "./ContinuePanel";
import { InlineToolbox } from "./InlineToolbox";
import { ChapterRewritePanel } from "./ChapterRewritePanel";
import { ContextDrawer } from "./ContextDrawer";
import {
  AiConversationDrawer,
  AI_CONVERSATION_ENABLED,
} from "./AiConversationDrawer";
import { GenrePicker } from "./GenrePicker";
import { GENRES } from "@/lib/wizard/wizard";
import { useGenreGate, toGenreDirective } from "@/lib/workbench/useGenreGate";
import { useAiConversation } from "@/lib/workbench/useAiConversation";
import { useChapterListCollapse } from "@/lib/workbench/useChapterListCollapse";
import { useFocusMode } from "@/lib/workbench/useFocusMode";
import { DirectivePanel, AiVerbsRow } from "./AiToolbar";
import { MobileContextBar } from "./MobileContextBar";
import { Toolbar } from "./WorkbenchToolbar";

interface WorkbenchProps {
  project: ProjectResponse;
  // 当前章号（来自写作路由 `?chapter=N`）；缺省回退第 1 章。
  chapterNo?: number;
  // RSC 种入的已存草稿正文（GET .../draft）；无草稿（404）→ ""（空编辑器）。
  initialText?: string;
  // 大纲章节目录（GET .../outline）；无大纲 → 空数组（目录回退到仅当前章 + 去大纲提示）。
  chapters?: ChapterEntry[];
}

// 移动端右栏（目录/助手）经抽屉触达；桌面用三栏栅格。
type MobilePanel = "chapters" | "assistant" | null;

// M1：单章工作台。章节列表为占位（无章节列表端点）；默认第 1 章。
// WORKBENCH_CHAPTER_NO 移到 lib/workbench/chapter.ts（非客户端模块），供 Server Component 安全导入。

export function Workbench({
  project,
  chapterNo = WORKBENCH_CHAPTER_NO,
  initialText = "",
  chapters = [],
}: WorkbenchProps) {
  // 用已存草稿作初值；流式开始后由下方 effect 覆盖（流不会被初值反扑——
  // stream.state.text 起始为空，仅当 streaming/done/aborted 且变化才写回）。
  const [text, setText] = useState(initialText);
  const [mobilePanel, setMobilePanel] = useState<MobilePanel>(null);
  // 本章指令（T4-b）：自由文本 + 风格预设 → 写本章时组装传入 draft 生成。
  const [directive, setDirective] = useState("");
  const [presetIds, setPresetIds] = useState<string[]>([]);
  // 选区级 AI 动作（润色/再沟通）：编辑器上报的最新选区 + 结果卡开合。
  const [selection, setSelection] = useState<EditorSelection | null>(null);
  const [refineOpen, setRefineOpen] = useState(false);
  const [continueOpen, setContinueOpen] = useState(false);
  const [toolboxOpen, setToolboxOpen] = useState(false);
  // WFW-8：整章「再沟通/重写」结果卡开合（意见 → 流式重写一版 → 版本栈 → 接受替换整章）。
  const [rewriteOpen, setRewriteOpen] = useState(false);
  // WFW-7 / P1-5：首次写章的极轻 genre 采集门。项目无题材 → 正文上方常驻一条内联「题材」选择条
  // （非弹窗），作者点一个题材再写；仅临时并入本次指令、不落库，避免无题材 slop，且第一次发送不被打断。
  const genreGate = useGenreGate(project.genre ?? null);
  // WFW-6 上下文速查抽屉：加法式、flag 灰度；与三张 AI 结果卡互不干扰。
  const [contextOpen, setContextOpen] = useState(false);
  // AC-3 AI 对话抽屉：Workbench 级单实例（append 即使抽屉关着也能触发）；flag 灰度。
  const [conversationOpen, setConversationOpen] = useState(false);
  const conversation = useAiConversation(project.id, chapterNo);
  // P2-2：桌面「目录」列可收起（记忆状态）；收起时把宽让给正文，窄轨留一个展开入口。
  const chapterList = useChapterListCollapse();
  // P3-4：专注写作开关（记忆状态）——开启隐藏左侧图标导航 + 目录 TOC，让宽给正文。
  const focusMode = useFocusMode();
  const conversationTriggerRef = useRef<HTMLButtonElement>(null);
  const toast = useToast();
  const autosave = useAutosave(project.id, chapterNo, initialText);
  const stream = useDraftStream();
  const lastStreamText = useRef("");
  const canRefine = selection !== null && selection.text.trim().length > 0;
  const chapterTriggerRef = useRef<HTMLButtonElement>(null);
  const assistantTriggerRef = useRef<HTMLButtonElement>(null);
  const contextTriggerRef = useRef<HTMLButtonElement>(null);
  // P3-7 流式跟随：正文滚动容器引用（纯展示层，不触碰 SSE/流式数据）。
  const editorScrollRef = useRef<HTMLDivElement>(null);

  // 流式 token 累积进编辑器（打字机）；停止/结束后已生成部分留在草稿。
  useEffect(() => {
    const streamed = stream.state.text;
    if (
      (stream.state.phase === "streaming" ||
        stream.state.phase === "done" ||
        stream.state.phase === "aborted") &&
      streamed !== lastStreamText.current
    ) {
      lastStreamText.current = streamed;
      setText(streamed);
      autosave.onChange(streamed);
    }
  }, [stream.state.phase, stream.state.text, autosave]);

  // P3-7 流式跟随：流式且正文增长时把滚动容器贴到底，让新生成的段落保持可见。
  // 纯展示层：只读既有 text/streaming 展示态，瞬时定位（无动画，天然尊重 prefers-reduced-motion）。
  useEffect(() => {
    if (!stream.isStreaming) return;
    const el = editorScrollRef.current;
    if (!el) return;
    el.scrollTop = el.scrollHeight;
  }, [text, stream.isStreaming]);

  // 题材 + 三槽指令合并为一条写章指令（题材前置）；effectiveGenre 无 → 仅原指令。
  const startWrite = (effectiveGenre: string | null): void => {
    const base = composeDirective(directive, presetIds);
    const merged = [toGenreDirective(effectiveGenre), base]
      .filter((part) => part.length > 0)
      .join("；");
    void stream.start(project.id, chapterNo, merged);
  };

  const onWrite = (): void => {
    // 无题材且未点选 → 引导先点上方常驻「题材」条再写（HITL：不静默生成无题材 slop）。
    // 选择条一直可见，理想路径是发送前已选好，第一次「写本章」即顺滑流式、不被弹窗打断。
    if (genreGate.needsGenre && genreGate.chosenGenre === null) {
      toast("先在上方选个题材，AI 写得更贴合、少套话。", "info");
      return;
    }
    startWrite(genreGate.effectiveGenre);
  };

  const togglePreset = (id: string): void => {
    setPresetIds((prev) =>
      prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id],
    );
  };

  const onEditorChange = (value: string): void => {
    setText(value);
    autosave.onChange(value);
  };

  // 接受润色/再沟通产出：按内容重锚把选段替换为产出并落草稿；原文已变则提示重选（不盲替换）。
  const onAcceptRefine = (refined: string): void => {
    if (selection) {
      const next = applyRefinement(text, selection.text, refined, {
        start: selection.start,
        end: selection.end,
      });
      if (next === null) {
        toast("正文已改动，找不到原选段，请重新选择后再润色。", "error");
      } else {
        setText(next);
        autosave.onChange(next);
      }
    }
    setRefineOpen(false);
    setSelection(null);
  };

  // 四张 AI 结果卡（润色/续写/工具箱/整章重写）互斥，避免同时占位。
  // 润色以选区为对象：无选区时不静默失败，给出可见提示引导先选段（P0-4，替代 hover-only title）。
  const openRefine = (): void => {
    if (!canRefine) {
      toast("先在正文里选中一段再润色", "info");
      return;
    }
    setContinueOpen(false);
    setToolboxOpen(false);
    setRewriteOpen(false);
    setRefineOpen(true);
  };

  // 续写前先 flush 自动保存，确保 continue 读到的是最新草稿（with_prior_chapter 读库）。
  const openContinue = (): void => {
    autosave.flush();
    setRefineOpen(false);
    setToolboxOpen(false);
    setRewriteOpen(false);
    setContinueOpen(true);
  };

  const openToolbox = (): void => {
    setRefineOpen(false);
    setContinueOpen(false);
    setRewriteOpen(false);
    setToolboxOpen(true);
  };

  const openRewrite = (): void => {
    setRefineOpen(false);
    setContinueOpen(false);
    setToolboxOpen(false);
    setRewriteOpen(true);
  };

  // 接受某一版整章重写 → 替换整章正文并落草稿（HITL，作者点选才落）。
  const onAcceptRewrite = (next: string): void => {
    setText(next);
    autosave.onChange(next);
    setRewriteOpen(false);
  };

  // 追加一段文本到章末并落草稿（续写候选 / 工具箱产物共用）。
  const appendToDraft = (chunk: string): void => {
    const base = text.trimEnd();
    const next = base.length > 0 ? `${base}\n\n${chunk}` : chunk;
    setText(next);
    autosave.onChange(next);
  };

  const onInsertContinuation = (candidate: string): void => {
    appendToDraft(candidate);
    setContinueOpen(false);
  };

  // 从「AI 对话」历史再接受（复用 DRAFT-only HITL：只回填编辑器草稿，不绕开验收事务——不变量 #3）。
  // 返回 true=成功则抽屉自关，露出改动后的编辑器 + 成功 toast；refine 找不到原选段返回 false + 漂移提示。
  const onReplaceChapterFromHistory = (content: string): boolean => {
    setText(content);
    autosave.onChange(content);
    toast("已替换整章。", "success");
    return true;
  };

  const onAppendDraftFromHistory = (content: string): boolean => {
    appendToDraft(content);
    toast("已加到章末。", "success");
    return true;
  };

  const onRefillSegmentFromHistory = (
    segment: string,
    refined: string,
  ): boolean => {
    // 合成零区间强制 slice 校验失败 → 走 indexOf 按存档的原选段重锚；找不到则不盲替换。
    const next = applyRefinement(text, segment, refined, { start: 0, end: 0 });
    if (next === null) {
      toast("正文已改动，找不到原选段，无法替换。", "error");
      return false;
    }
    setText(next);
    autosave.onChange(next);
    toast("已替换这段。", "success");
    return true;
  };

  // 字数统计非空白字符（与中文读者直觉一致：标点/空格不计入正文体量）。
  const wordCount = text.replace(/\s+/g, "").length;
  const closePanel = (): void => setMobilePanel(null);

  // 桌面栅格列宽：专注模式撤掉目录 TOC 列（仅正文 + 右栏）；否则按目录列收起/展开取宽。
  const gridCols = focusMode.focus
    ? "xl:grid-cols-[1fr_18rem]"
    : chapterList.collapsed
      ? "xl:grid-cols-[2.75rem_1fr_18rem]"
      : "xl:grid-cols-[12rem_1fr_18rem]";

  // 流式里程碑播报（仅终结句，非逐 token）：完成/停止/失败时写入 role=status 区。
  const liveMessage = ((): string => {
    switch (stream.state.phase) {
      case "done":
        return `本章生成完成，共 ${wordCount} 字`;
      case "aborted":
        return "已停止";
      case "error":
        return stream.state.error
          ? friendlyError(stream.state.error.code, stream.state.error.message)
              .text
          : "本章生成失败，请稍后重试。";
      default:
        return "";
    }
  })();

  return (
    <AppShell
      title={`〈${project.title}〉`}
      subtitle={`第 ${chapterNo} 章`}
      projectId={project.id}
      activeNav="write"
      hideNav={focusMode.focus}
    >
      <div
        className={`grid min-h-[calc(100vh-var(--chrome,4rem))] grid-cols-1 xl:h-[calc(100vh-var(--chrome,4rem))] ${gridCols}`}
      >
        {focusMode.focus ? null : (
          <ChapterList
            projectId={project.id}
            chapters={chapters}
            currentChapterNo={chapterNo}
            collapsed={chapterList.collapsed}
            onToggle={chapterList.toggle}
          />
        )}

        <section className="flex min-w-0 flex-col bg-bg">
          <MobileContextBar
            chapterNo={chapterNo}
            onOpenChapters={() => setMobilePanel("chapters")}
            onOpenAssistant={() => setMobilePanel("assistant")}
            chapterTriggerRef={chapterTriggerRef}
            assistantTriggerRef={assistantTriggerRef}
          />
          {genreGate.needsGenre ? (
            // 项目无题材：正文上方常驻内联题材条（非弹窗），发送前选好即顺滑写章（P1-5）。
            <GenrePicker
              genres={GENRES}
              value={genreGate.chosenGenre}
              onPick={genreGate.setChosenGenre}
            />
          ) : null}
          <DirectivePanel
            directive={directive}
            onDirectiveChange={setDirective}
            presetIds={presetIds}
            onTogglePreset={togglePreset}
            defaultOpen={initialText.trim().length === 0}
            streaming={stream.isStreaming}
            onWrite={onWrite}
            onStop={stream.stop}
          />
          <AiVerbsRow
            streaming={stream.isStreaming}
            onContinue={openContinue}
            onRefineSelection={openRefine}
            onRewrite={openRewrite}
            onToolbox={openToolbox}
          />
          {refineOpen && canRefine && selection ? (
            <RefinePanel
              projectId={project.id}
              chapterNo={chapterNo}
              original={selection.text}
              onAccept={onAcceptRefine}
              onReaccept={onRefillSegmentFromHistory}
              conversation={conversation}
              onClose={() => setRefineOpen(false)}
            />
          ) : null}
          {continueOpen ? (
            <ContinuePanel
              projectId={project.id}
              chapterNo={chapterNo}
              onInsert={onInsertContinuation}
              appendMessages={conversation.appendMessages}
              onClose={() => setContinueOpen(false)}
            />
          ) : null}
          {toolboxOpen ? (
            <InlineToolbox
              projectId={project.id}
              chapterNo={chapterNo}
              manuscriptText={text}
              appendMessages={conversation.appendMessages}
              onInsertText={(chunk) => {
                appendToDraft(chunk);
                setToolboxOpen(false);
              }}
              onClose={() => setToolboxOpen(false)}
            />
          ) : null}
          {rewriteOpen ? (
            <ChapterRewritePanel
              projectId={project.id}
              chapterNo={chapterNo}
              currentDraft={text}
              onAccept={onAcceptRewrite}
              conversation={conversation}
              onClose={() => setRewriteOpen(false)}
            />
          ) : null}
          <div ref={editorScrollRef} className="flex-1 overflow-auto px-6 py-8">
            {chapters.length === 0 ? (
              <StatusNote variant="info" className="mb-4">
                尚无大纲，将按设定自由生成。
              </StatusNote>
            ) : null}
            <Editor
              value={text}
              onChange={onEditorChange}
              streaming={stream.isStreaming}
              onSelectionChange={setSelection}
            />
          </div>
          <Toolbar
            projectId={project.id}
            chapterNo={chapterNo}
            wordCount={wordCount}
            savedLabel={autosave.savedLabel}
            saveStatus={autosave.status}
            streaming={stream.isStreaming}
            streamError={stream.state.error}
            liveMessage={liveMessage}
            onStop={stream.stop}
            focus={focusMode.focus}
            onToggleFocus={focusMode.toggle}
            onOpenContext={() => setContextOpen(true)}
            contextTriggerRef={contextTriggerRef}
            onOpenConversation={() => setConversationOpen(true)}
            conversationTriggerRef={conversationTriggerRef}
          />
        </section>

        <ChapterAssistant projectId={project.id} chapterNo={chapterNo} />
      </div>

      {/* 窄屏 / 中屏(1024–1280)：目录 / 本章助手经抽屉触达；≥xl 已在三栏栅格里直显。 */}
      <Drawer
        open={mobilePanel === "chapters"}
        onClose={closePanel}
        side="left"
        label="目录"
        triggerRef={chapterTriggerRef}
      >
        <ChapterListContent
          projectId={project.id}
          chapters={chapters}
          currentChapterNo={chapterNo}
        />
      </Drawer>
      <Drawer
        open={mobilePanel === "assistant"}
        onClose={closePanel}
        side="right"
        label="本章参考"
        triggerRef={assistantTriggerRef}
      >
        <AssistantContent projectId={project.id} chapterNo={chapterNo} />
      </Drawer>

      {/* WFW-6 上下文速查：视口无关的右侧 slide-over；旧侧栏/全宽页路由保留、可回滚。 */}
      <ContextDrawer
        projectId={project.id}
        chapterNo={chapterNo}
        open={contextOpen}
        onClose={() => setContextOpen(false)}
        triggerRef={contextTriggerRef}
      />

      {/* AC-3 AI 对话：右侧 slide-over 气泡视图；从历史再接受只回填草稿，不绕验收事务。flag 灰度。 */}
      {AI_CONVERSATION_ENABLED ? (
        <AiConversationDrawer
          open={conversationOpen}
          onClose={() => setConversationOpen(false)}
          conversation={conversation}
          currentChapterNo={chapterNo}
          onReplaceChapter={onReplaceChapterFromHistory}
          onAppendDraft={onAppendDraftFromHistory}
          onRefillSegment={onRefillSegmentFromHistory}
          triggerRef={conversationTriggerRef}
        />
      ) : null}
    </AppShell>
  );
}
