// 本章注入透明（B0/F1）纯逻辑：入选理由 / 实体类型 → 中文徽标。
// 纯函数，便于 node 环境单测；渲染层只管样式。

import type { components } from "@/lib/api/schema";

export type InjectionResponse = components["schemas"]["InjectionResponse"];
export type InjectionEntity = components["schemas"]["InjectionEntity"];
export type InjectionEntityRef = components["schemas"]["InjectionEntityRef"];
export type InjectionOverrideRequest =
  components["schemas"]["InjectionOverrideRequest"];

// recent_n 合法区间（与后端 RECENT_N_MIN/MAX 对齐；越界后端 422）。
export const RECENT_N_MIN = 1;
export const RECENT_N_MAX = 20;

// SelectionReason → 作者可读徽标（对齐 ARCH §3.4 的四来源 + 作者置顶）。
export const REASON_LABELS: Record<string, string> = {
  explicit_beat: "本章点名",
  main_character: "主角常驻",
  recent_digest: "近章出现",
  foreshadow_window: "伏笔窗口",
  author_pin: "作者置顶",
};

// EntityKind → 中文。
export const KIND_LABELS: Record<string, string> = {
  character: "角色",
  world_entity: "设定",
};

// 未知 code 时回退原值（不吞，便于发现新理由）。
export function reasonLabel(reason: string): string {
  return REASON_LABELS[reason] ?? reason;
}

export function kindLabel(kind: string): string {
  return KIND_LABELS[kind] ?? kind;
}

// ---- 作者覆盖（B0 可控版）纯函数：从响应推导当前覆盖 + 不可变地施加单个改动 ----

const refKey = (r: InjectionEntityRef): string => `${r.kind}:${r.name}`;
const sameRef = (a: InjectionEntityRef, b: InjectionEntityRef): boolean =>
  a.kind === b.kind && a.name === b.name;

// 从注入响应回显字段抽出当前覆盖（PUT 回放服务端确定结果后驱动 UI）。
export function currentOverride(
  data: InjectionResponse,
): InjectionOverrideRequest {
  return {
    pinned: [...(data.pinned ?? [])],
    excluded: [...(data.excluded ?? [])],
    recent_n: data.recent_n,
  };
}

export function isPinned(
  override: InjectionOverrideRequest,
  ref: InjectionEntityRef,
): boolean {
  return (override.pinned ?? []).some((r) => sameRef(r, ref));
}

const without = (
  list: InjectionEntityRef[] | undefined,
  ref: InjectionEntityRef,
): InjectionEntityRef[] => (list ?? []).filter((r) => !sameRef(r, ref));

// 切换 pin：已置顶 → 取消；否则置顶并从排除列表移除（一个实体不同时 pin+排除）。
export function withPinToggled(
  override: InjectionOverrideRequest,
  ref: InjectionEntityRef,
): InjectionOverrideRequest {
  const pinnedNow = isPinned(override, ref);
  return {
    ...override,
    pinned: pinnedNow
      ? without(override.pinned, ref)
      : [...(override.pinned ?? []), { kind: ref.kind, name: ref.name }],
    excluded: without(override.excluded, ref),
  };
}

// 排除：加入排除列表，并从置顶列表移除。重复排除幂等（先去重再加）。
export function withExcluded(
  override: InjectionOverrideRequest,
  ref: InjectionEntityRef,
): InjectionOverrideRequest {
  return {
    ...override,
    pinned: without(override.pinned, ref),
    excluded: [
      ...without(override.excluded, ref),
      { kind: ref.kind, name: ref.name },
    ],
  };
}

// 恢复被排除的实体（回到纯自动选择判定）。
export function withRestored(
  override: InjectionOverrideRequest,
  ref: InjectionEntityRef,
): InjectionOverrideRequest {
  return { ...override, excluded: without(override.excluded, ref) };
}

// 设置近况回看章数（钳到合法区间，避免后端 422）。
export function withRecentN(
  override: InjectionOverrideRequest,
  n: number,
): InjectionOverrideRequest {
  const clamped = Math.max(RECENT_N_MIN, Math.min(RECENT_N_MAX, Math.round(n)));
  return { ...override, recent_n: clamped };
}

export { refKey };
