/**
 * Wire → domain normalization for the conversation transcript read (LS7).
 *
 * Mirrors the LS6 backend DTO (`crates/app-tauri/src/dto.rs`): `TurnPageDto`
 * (camelCase `turns` / `hasMore` / `nextAnchor`), `TurnViewDto`
 * (`id` / `atMs` / `role` / `source` / `text` / `textLen`) and the serde-tagged
 * `TurnSourceDto` (`{ kind: "human" }` | `{ kind: "agent", agentId }`). The
 * `source` mapping is calqued on `workStateNormalization.ts`.
 */

import type { TurnPage, TurnRole, TurnSource, TurnView } from "@/domain";

type RecordLike = Record<string, unknown>;

function isRecord(value: unknown): value is RecordLike {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}

function stringValue(value: unknown, fallback = ""): string {
  return typeof value === "string" ? value : fallback;
}

function numberValue(value: unknown, fallback = 0): number {
  return typeof value === "number" && Number.isFinite(value) ? value : fallback;
}

function arrayValue(value: unknown): unknown[] {
  return Array.isArray(value) ? value : [];
}

/** Mirror of LS6 `TurnSourceDto` (serde tag `kind`, camelCase `agentId`). */
function normalizeSource(value: unknown): TurnSource {
  if (!isRecord(value)) return { kind: "human" };
  if (value.kind === "agent") {
    return { kind: "agent", agentId: stringValue(value.agentId, "unknown") };
  }
  return { kind: "human" };
}

/** Mirror of the camelCase-serialized `TurnRole` (`prompt`/`response`/`toolActivity`). */
function normalizeRole(value: unknown): TurnRole {
  return value === "response" || value === "toolActivity" ? value : "prompt";
}

function normalizeTurn(value: unknown, index: number): TurnView {
  const turn = isRecord(value) ? value : {};
  const text = stringValue(turn.text);
  return {
    id: stringValue(turn.id, `turn-${index}`),
    atMs: numberValue(turn.atMs, index),
    role: normalizeRole(turn.role),
    source: normalizeSource(turn.source),
    text,
    textLen: numberValue(turn.textLen, text.length),
  };
}

/** Maps a raw `TurnPageDto` payload to the domain {@link TurnPage}. */
export function normalizeTurnPage(value: unknown): TurnPage {
  const page = isRecord(value) ? value : {};
  const nextAnchor = page.nextAnchor;
  return {
    turns: arrayValue(page.turns).map(normalizeTurn),
    hasMore: page.hasMore === true,
    ...(typeof nextAnchor === "string" ? { nextAnchor } : {}),
  };
}
