"use client";

import { useRef, type ReactNode, type RefObject } from "react";

import { locateInDraft } from "@/lib/review/locate";
import type { ReviewConflict } from "@/lib/review/sse";

interface AnnotatedTextProps {
  value: string;
  onChange: (next: string) => void;
  conflicts: ReviewConflict[];
  // 当前聚焦的冲突下标（来自报告卡「跳转」/锚点），用于锚点高亮联动。
  focusedIndex: number | null;
  onAnchorClick: (index: number) => void;
  // 转发给可编辑 textarea，供父组件 setSelectionRange 定位/高亮问题区域。
  editorRef?: RefObject<HTMLTextAreaElement | null>;
}

// 高亮叠层编辑器：背景层渲染带 <mark> 高亮的正文，前景透明 textarea 负责编辑。
// 两层必须共享同一盒模型/排版常量，否则高亮与文字像素错位。
const TYPO =
  "box-border w-full font-serif text-[17px] leading-[1.9] tracking-normal whitespace-pre-wrap break-words";

// 把终稿按已定位的冲突区间切成 [纯文本 | <mark> | …]；<mark> 带 id 供父组件滚动定位。
// 区间按 start 排序，重叠区间保留先到者（跳过后者），避免标签嵌套。
function buildSegments(value: string, conflicts: ReviewConflict[]): ReactNode[] {
  const spans = conflicts
    .map((c, i) => ({ i, loc: locateInDraft(value, c) }))
    .filter(
      (x): x is { i: number; loc: { start: number; end: number } } =>
        x.loc !== null,
    )
    .sort((a, b) => a.loc.start - b.loc.start);

  const nodes: ReactNode[] = [];
  let cursor = 0;
  for (const { i, loc } of spans) {
    if (loc.start < cursor) continue; // 与已保留区间重叠 → 跳过
    if (loc.start > cursor) nodes.push(value.slice(cursor, loc.start));
    nodes.push(
      <mark
        key={`mark-${i}`}
        id={`draft-mark-${i}`}
        className="draft-mark text-ink"
      >
        {value.slice(loc.start, loc.end)}
      </mark>,
    );
    cursor = loc.end;
  }
  if (cursor < value.length) nodes.push(value.slice(cursor));
  return nodes;
}

// 正文就地编辑 + 冲突锚点（UX §8.3 / §6.1）。
// 顶部一排朱砂锚点：每条冲突一枚，点击=定位到正文对应区域（父组件在 textarea 选中并滚动）。
// 正文本体=高亮叠层编辑器：可直接改稿；冲突原文以朱砂淡底持续高亮，点锚点滚到并闪烁。
export function AnnotatedText({
  value,
  onChange,
  conflicts,
  focusedIndex,
  onAnchorClick,
  editorRef,
}: AnnotatedTextProps) {
  const backdropRef = useRef<HTMLDivElement>(null);
  const segments = buildSegments(value, conflicts);
  // 只为能在正文里定位到的冲突渲染锚点（其余如涉及摘要/跨章的冲突不在正文，点了也定位不到）。
  const anchorable = conflicts
    .map((c, i) => ({ c, i }))
    .filter(({ c }) => locateInDraft(value, c) !== null);
  return (
    <div className="flex flex-col gap-3">
      {anchorable.length > 0 ? (
        <div className="flex flex-wrap gap-2 border-b border-line pb-3">
          {anchorable.map(({ c, i }) => (
            <button
              key={`${c.type}-${c.where}-${i}`}
              type="button"
              id={`anchor-${i}`}
              onClick={() => onAnchorClick(i)}
              aria-current={focusedIndex === i ? "true" : undefined}
              className={`conflict-anchor rounded px-2 py-0.5 text-xs ${
                focusedIndex === i
                  ? "bg-cinnabar text-panel"
                  : "text-conflict hover:bg-[var(--color-conflict)]/10"
              }`}
              title={`${c.type}：${c.where || "正文"} — 点击定位到正文`}
            >
              <span aria-hidden="true">⌇</span> {c.type}
              {c.where ? ` · ${c.where}` : ""}
            </button>
          ))}
        </div>
      ) : null}
      <label htmlFor="final-text" className="sr-only">
        终稿正文
      </label>
      <div className="relative min-h-[40vh] w-full bg-transparent">
        {/* 背景高亮层：在文档流中决定高度（撑满全文），仅展示（不可交互）。 */}
        <div
          ref={backdropRef}
          data-draft-backdrop
          aria-hidden="true"
          className={`${TYPO} pointer-events-none relative select-none text-ink`}
        >
          {value ? (
            segments
          ) : (
            <span className="text-ink-soft/60">
              （无待审正文，先去写作页起草本章）
            </span>
          )}
          {"\n"}
        </div>
        {/* 前景编辑层：文字透明（由背景层显示），仅保留光标；无内部滚动（页面滚动）。 */}
        <textarea
          ref={editorRef}
          id="final-text"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          spellCheck={false}
          className={`${TYPO} absolute inset-0 resize-none overflow-hidden border-0 bg-transparent text-transparent caret-[color:var(--color-ink)] outline-none focus:outline-none`}
        />
      </div>
    </div>
  );
}
