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

interface WorkbenchProps {
  project: ProjectResponse;
  // RSC 种入的已存草稿正文（GET .../draft）；无草稿（404）→ ""（空编辑器）。
  initialText?: string;
}

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

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

export function Workbench({ project, initialText = "" }: WorkbenchProps) {
  const chapterNo = WORKBENCH_CHAPTER_NO;
  // 用已存草稿作初值；流式开始后由下方 effect 覆盖（流不会被初值反扑——
  // stream.state.text 起始为空，仅当 streaming/done/aborted 且变化才写回）。
  const [text, setText] = useState(initialText);
  const [mobilePanel, setMobilePanel] = useState<MobilePanel>(null);
  const autosave = useAutosave(project.id, chapterNo);
  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);
  };

  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-4rem)] grid-cols-1 lg:grid-cols-[12rem_1fr_18rem]">
        <ChapterList currentChapterNo={chapterNo} />

        <section className="flex min-w-0 flex-col bg-bg">
          <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 currentChapterNo={chapterNo} />
      </Drawer>
      <Drawer
        open={mobilePanel === "assistant"}
        onClose={closePanel}
        side="right"
        label="本章助手"
      >
        <AssistantContent projectId={project.id} chapterNo={chapterNo} />
      </Drawer>
    </AppShell>
  );
}

// 写章失败提示：友好文案（不暴露 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>
  );
}
