"use client";

import Link from "next/link";
import { useEffect, useRef, useState } from "react";

import { AppShell } from "@/components/AppShell";
import { Drawer } from "@/components/Drawer";
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, STYLE_PRESETS } from "@/lib/workbench/directive";
import { ChapterList, ChapterListContent } from "./ChapterList";
import { ChapterAssistant, AssistantContent } from "./ChapterAssistant";
import { Editor } from "./Editor";

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[]>([]);
  const autosave = useAutosave(project.id, chapterNo, initialText);
  const stream = useDraftStream();
  const lastStreamText = useRef("");

  // 流式 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]);

  const onWrite = (): void => {
    void stream.start(
      project.id,
      chapterNo,
      composeDirective(directive, presetIds),
    );
  };

  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 wordCount = text.length;
  const closePanel = (): void => setMobilePanel(null);

  return (
    <AppShell
      title={`〈${project.title}〉`}
      subtitle={`第 ${chapterNo} 章`}
      projectId={project.id}
      activeNav="write"
    >
      <div className="grid h-[calc(100vh-var(--chrome,4rem))] grid-cols-1 lg:grid-cols-[12rem_1fr_18rem]">
        <ChapterList
          projectId={project.id}
          chapters={chapters}
          currentChapterNo={chapterNo}
        />

        <section className="flex min-w-0 flex-col bg-bg">
          <DirectivePanel
            directive={directive}
            onDirectiveChange={setDirective}
            presetIds={presetIds}
            onTogglePreset={togglePreset}
          />
          <div className="flex-1 overflow-auto px-6 py-8">
            <Editor
              value={text}
              onChange={onEditorChange}
              streaming={stream.isStreaming}
            />
          </div>
          <Toolbar
            projectId={project.id}
            chapterNo={chapterNo}
            wordCount={wordCount}
            savedLabel={autosave.savedLabel}
            saveStatus={autosave.status}
            streaming={stream.isStreaming}
            streamError={stream.state.error}
            onWrite={onWrite}
            onStop={stream.stop}
            onOpenChapters={() => setMobilePanel("chapters")}
            onOpenAssistant={() => setMobilePanel("assistant")}
          />
        </section>

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

      {/* 移动端：目录 / 本章助手经抽屉触达（桌面已在栅格里，抽屉 lg:hidden）。 */}
      <Drawer
        open={mobilePanel === "chapters"}
        onClose={closePanel}
        side="left"
        label="目录"
      >
        <ChapterListContent
          projectId={project.id}
          chapters={chapters}
          currentChapterNo={chapterNo}
        />
      </Drawer>
      <Drawer
        open={mobilePanel === "assistant"}
        onClose={closePanel}
        side="right"
        label="本章助手"
      >
        <AssistantContent projectId={project.id} chapterNo={chapterNo} />
      </Drawer>
    </AppShell>
  );
}

interface DirectivePanelProps {
  directive: string;
  onDirectiveChange: (value: string) => void;
  presetIds: readonly string[];
  onTogglePreset: (id: string) => void;
}

// 本章指令面板（T4-b）：可折叠的 textarea + 风格快捷预设 chips。
// 默认折叠（不抢编辑视野）；指令覆盖/补充大纲节拍，写本章时组装传入生成。
function DirectivePanel({
  directive,
  onDirectiveChange,
  presetIds,
  onTogglePreset,
}: DirectivePanelProps) {
  return (
    <details className="border-b border-line bg-panel px-6 py-2">
      <summary className="cursor-pointer text-sm text-ink-soft hover:text-cinnabar">
        本章指令（可选）
      </summary>
      <div className="mt-2 space-y-2">
        <label className="block">
          <span className="sr-only">本章指令</span>
          <textarea
            value={directive}
            onChange={(e) => onDirectiveChange(e.target.value)}
            rows={2}
            placeholder="本章想怎么写？（可选，覆盖/补充大纲节拍）"
            className="w-full resize-y rounded border border-line bg-bg px-3 py-2 text-sm text-ink placeholder:text-ink-soft focus:border-cinnabar focus:outline-none"
          />
        </label>
        <div className="flex flex-wrap gap-2">
          {STYLE_PRESETS.map((preset) => {
            const active = presetIds.includes(preset.id);
            return (
              <button
                key={preset.id}
                type="button"
                aria-pressed={active}
                onClick={() => onTogglePreset(preset.id)}
                className={
                  active
                    ? "rounded-full border border-cinnabar bg-cinnabar px-3 py-1 text-xs text-panel"
                    : "rounded-full border border-line px-3 py-1 text-xs text-ink-soft hover:border-cinnabar hover:text-cinnabar"
                }
              >
                {preset.label}
              </button>
            );
          })}
        </div>
      </div>
    </details>
  );
}

// 写章失败提示：友好文案（不暴露 raw code）+ 可选「去设置」动作（F4）。
function StreamErrorNote({
  streamError,
}: {
  streamError: { code: string; message: string };
}) {
  const friendly = friendlyError(streamError.code, streamError.message);
  return (
    <p className="mb-2 text-sm text-conflict">
      {friendly.text}
      {friendly.actionHref ? (
        <>
          {" "}
          <Link
            href={friendly.actionHref}
            className="underline hover:text-cinnabar"
          >
            {friendly.actionLabel}
          </Link>
        </>
      ) : null}
    </p>
  );
}

interface ToolbarProps {
  projectId: string;
  chapterNo: number;
  wordCount: number;
  savedLabel: string | null;
  saveStatus: ReturnType<typeof useAutosave>["status"];
  streaming: boolean;
  streamError: { code: string; message: string } | null;
  onWrite: () => void;
  onStop: () => void;
  onOpenChapters: () => void;
  onOpenAssistant: () => void;
}

function Toolbar({
  projectId,
  chapterNo,
  wordCount,
  savedLabel,
  saveStatus,
  streaming,
  streamError,
  onWrite,
  onStop,
  onOpenChapters,
  onOpenAssistant,
}: ToolbarProps) {
  return (
    <div className="border-t border-line bg-panel px-4 py-3 sm:px-6">
      {streamError ? <StreamErrorNote streamError={streamError} /> : null}
      <div className="flex flex-wrap items-center gap-2 sm:gap-3">
        <button
          type="button"
          onClick={onOpenChapters}
          className="rounded border border-line px-3 py-2 text-sm text-ink hover:border-cinnabar hover:text-cinnabar lg:hidden"
        >
          目录
        </button>
        {streaming ? (
          <button
            type="button"
            onClick={onStop}
            className="rounded border border-conflict px-4 py-2 text-sm text-conflict"
          >
            停
          </button>
        ) : (
          <button
            type="button"
            onClick={onWrite}
            className="rounded bg-cinnabar px-4 py-2 text-sm text-panel hover:opacity-90"
          >
            ✍ 写本章
          </button>
        )}
        {streaming ? (
          <span className="font-mono text-xs text-cinnabar motion-safe:animate-pulse">
            生成中… {wordCount.toLocaleString("en-US")} 字
          </span>
        ) : (
          <span className="font-mono text-xs text-ink-soft">
            字数 {wordCount.toLocaleString("en-US")}
          </span>
        )}
        <Link
          href={`/projects/${projectId}/outline`}
          className="rounded border border-line px-4 py-2 text-sm text-ink hover:border-cinnabar hover:text-cinnabar"
        >
          大纲
        </Link>
        <Link
          href={`/projects/${projectId}/foreshadow`}
          className="rounded border border-line px-4 py-2 text-sm text-ink hover:border-cinnabar hover:text-cinnabar"
        >
          伏笔
        </Link>
        <button
          type="button"
          onClick={onOpenAssistant}
          className="rounded border border-line px-3 py-2 text-sm text-ink hover:border-cinnabar hover:text-cinnabar lg:hidden"
        >
          助手
        </button>
        <Link
          href={`/projects/${projectId}/review?chapter=${chapterNo}`}
          className="rounded border border-cinnabar px-4 py-2 text-sm text-cinnabar hover:bg-[var(--color-cinnabar-wash)]"
        >
          审稿 →
        </Link>
        <span className="ml-auto font-mono text-xs text-ink-soft">
          {saveStatus === "saving"
            ? "保存中…"
            : saveStatus === "error"
              ? "保存失败"
              : (savedLabel ?? "尚未保存")}
        </span>
      </div>
    </div>
  );
}
