// AI 对话（聊天记录）纯视图模型：把 append-only 的 AiMessageView 扁平流归组成可渲染的
// 线程/分区结构 + kind 标签/徽标/气泡方位映射。无 React/IO，确定性纯函数，供抽屉与单测共用。
// 排序纪律（守 AC 契约）：组内与线程都按 (created_at ASC, seq ASC)——绝不单靠 created_at
// （同一 append 批次共享 created_at，靠 repo 赋的 seq 消歧，这正是后端加 seq 的原因）。

import type { AiMessageView } from "@/lib/api/types";
import type { BadgeVariant } from "@/lib/ui/variants";

// v1 记录的五类交互（与后端 AiKind Literal 对齐）。
export type AiKind = "refine" | "rewrite" | "clarify" | "continue" | "generator";

// 抽屉里对某条 ai 产出可执行的接受动作（复用编辑器既有 DRAFT-only HITL 回调，不绕开验收事务）。
export type AcceptAction = "replace_chapter" | "append_draft" | "refill_segment";

export const KIND_LABEL: Record<AiKind, string> = {
  refine: "润色",
  rewrite: "整章重写",
  clarify: "反问澄清",
  continue: "续写",
  generator: "工具箱",
};

export const KIND_BADGE: Record<AiKind, BadgeVariant> = {
  refine: "accent",
  rewrite: "warning",
  clarify: "info",
  continue: "success",
  generator: "neutral",
};

// kind → 中文标签；未知 kind（后端可零迁移新增）回退原始串，永不崩。
export function kindLabel(kind: string): string {
  return KIND_LABEL[kind as AiKind] ?? kind;
}

// kind → 徽标变体；未知 kind 回退中性徽标。
export function kindBadge(kind: string): BadgeVariant {
  return KIND_BADGE[kind as AiKind] ?? "neutral";
}

// 气泡方位：作者靠右、AI 靠左（对话视图约定）。
export function bubbleSide(role: string): "left" | "right" {
  return role === "author" ? "right" : "left";
}

// 一次往复交换（同 thread_id 归组），消息按 (created_at, seq) 升序。
export interface AiThread {
  threadId: string;
  kind: string;
  toolKey: string | null;
  chapterNo: number | null;
  messages: AiMessageView[];
}

// created_at → 毫秒时间戳（兼容 Z / +00:00 两种序列化；不可解析回退 0）。
function timeOf(iso: string): number {
  const t = Date.parse(iso);
  return Number.isNaN(t) ? 0 : t;
}

// 稳定定序比较器：先 created_at，再 seq（跨批 created_at 定序、批内 seq 消歧）。
function byTimeThenSeq(a: AiMessageView, b: AiMessageView): number {
  const dt = timeOf(a.created_at) - timeOf(b.created_at);
  return dt !== 0 ? dt : a.seq - b.seq;
}

// 扁平消息流 → 线程数组。组内按 (created_at, seq) 升序；线程按各自首条 (created_at, seq) 升序
// （老线程在前，新往复追加在后——契合聊天视图 + aria additions 在末尾播报新增）。
export function groupByThread(messages: readonly AiMessageView[]): AiThread[] {
  const groups = new Map<string, AiMessageView[]>();
  for (const msg of messages) {
    const bucket = groups.get(msg.thread_id);
    if (bucket) {
      bucket.push(msg);
    } else {
      groups.set(msg.thread_id, [msg]);
    }
  }

  const threads: AiThread[] = [];
  for (const [threadId, rows] of groups) {
    const sorted = [...rows].sort(byTimeThenSeq);
    const head = sorted[0];
    if (!head) continue; // 分组桶恒非空；仅为类型收窄。
    threads.push({
      threadId,
      kind: head.kind,
      toolKey: head.tool_key,
      chapterNo: head.chapter_no,
      messages: sorted,
    });
  }

  // 线程按首条消息定序（复用同一比较器，取每组已排序的 messages[0]）。
  return threads.sort((a, b) => {
    const ha = a.messages[0];
    const hb = b.messages[0];
    if (!ha || !hb) return 0;
    return byTimeThenSeq(ha, hb);
  });
}

// 线程按作用域分区：本章线程（chapterNo === 当前章）与项目级线程（chapterNo == null，工具箱）。
export interface ScopePartition {
  chapterThreads: AiThread[];
  projectThreads: AiThread[];
}

export function partitionByScope(
  threads: readonly AiThread[],
  currentChapterNo: number,
): ScopePartition {
  const chapterThreads: AiThread[] = [];
  const projectThreads: AiThread[] = [];
  for (const thread of threads) {
    if (thread.chapterNo === currentChapterNo) {
      chapterThreads.push(thread);
    } else if (thread.chapterNo === null) {
      projectThreads.push(thread);
    }
    // 其它章号（联合查询理论上不返回）：既不归本章也不归项目级，静默丢弃。
  }
  return { chapterThreads, projectThreads };
}

// 线程 kind → 抽屉里对 ai 气泡可执行的接受动作；clarify / 未知 kind 无接受动作。
export function acceptActionFor(thread: AiThread): AcceptAction | null {
  switch (thread.kind) {
    case "rewrite":
      return "replace_chapter";
    case "continue":
    case "generator":
      return "append_draft";
    case "refine":
      return "refill_segment";
    default:
      return null;
  }
}
