/**
 * Canonical systems — the GLOBAL area vocabulary every project's Systems can
 * map onto (milestone 307).
 *
 * The mapping is an ASSOCIATION, never a rename: a project's System keeps the
 * name the project gave it, and `canonical_id` only records which shared area
 * it is an instance of. An unmapped System is fully usable — the catalog is a
 * convergence aid, not a gate.
 */
import { apiGet, apiPost, apiPatch, apiPut } from "@/api/client";

export interface CanonicalSystem {
  id: number;
  name: string;
  /** The match key: lowercase, "&" folded to "and", punctuation collapsed. */
  slug: string;
  description: string | null;
  order_index: number;
  created_at: string | null;
  updated_at: string | null;
}

/**
 * A suggested mapping. `basis` is the whole point of showing it:
 * - `exact`   — the names differ only in spelling. Mechanical.
 * - `overlap` — they share a meaningful word. A judgment call the reviewer is
 *   making, and it must never be presented as if it were the first.
 */
export interface CanonicalMatch {
  id: number;
  name: string;
  basis: "exact" | "overlap";
  score?: number;
}

export interface MappingProposal {
  system_id: number;
  system_name: string;
  canonical_id: number;
  canonical_name: string;
  basis: "exact" | "overlap";
  score: number;
}

export async function listCanonicalSystems(): Promise<CanonicalSystem[]> {
  const data = await apiGet<{ canonical_systems: CanonicalSystem[] }>(
    "/api/canonical-systems",
  );
  return data.canonical_systems;
}

/** Admin only — a global list anyone can extend stops being shared. */
export async function createCanonicalSystem(data: {
  name: string;
  description?: string;
}): Promise<CanonicalSystem> {
  return apiPost("/api/canonical-systems", data);
}

export async function updateCanonicalSystem(
  id: number,
  data: Partial<{ name: string; description: string; order_index: number }>,
): Promise<CanonicalSystem> {
  return apiPatch(`/api/canonical-systems/${id}`, data);
}

/** Proposals for a project's UNMAPPED Systems. Reads only — nothing applied. */
export async function proposeMappings(projectId: number): Promise<MappingProposal[]> {
  const data = await apiGet<{ proposals: MappingProposal[] }>(
    `/api/projects/${projectId}/canonical-proposals`,
  );
  return data.proposals;
}

/** Apply or clear one mapping. `null` unmaps. */
export async function mapSystem(
  systemId: number,
  canonicalId: number | null,
): Promise<{ id: number; canonical_id: number | null }> {
  return apiPut(`/api/systems/${systemId}/canonical`, { canonical_id: canonicalId });
}
