// Per-link mapping (Wertstrom P6, Baustein 2). A SimVSM link only survives
// into a VsmConnection when BOTH endpoints resolved to a real (supported)
// VsmNode — a link touching an unsupported/annotation node (e.g. an
// informationFlow into a noteVSM marker) becomes a "missing relationship"
// (§14.4's own bucket name) in the report, never a dangling
// fromNodeId/toNodeId (lib/api/schemas.ts UpdateValueStreamMapBody's
// referential-integrity check would reject that outright at persist time —
// this module enforces the same invariant earlier, with a legible reason).

import type { VsmConnection } from '@/lib/vsm-types'
import type { SimVsmParsedLink } from './types'
import { classifyLink } from './mapping-registry'

export interface LinkMapOutcome {
  simvsmKey: string
  simvsmClass: string
  supported: boolean
  /** Only meaningful when `!supported` — the CLASS's own German label (e.g.
   * "Bild-Verknüpfung"), never the raw SimVSM class name (Review-Fix C17,
   * adversarial review PR #360 — same "no internal class name in the
   * primary label" rule node-mapper.ts's unsupported-node branch follows).
   * Absent for the missing-endpoint case (the CLASS itself is fine there —
   * report.ts never needs a class label for that bucket, see
   * unsupportedReason). */
  labelDe?: string
  reasonDe?: string
  /** Distinguishes the TWO distinct "not supported" causes report.ts must
   * count/word SEPARATELY (Review-Fix C18, adversarial review PR #360):
   * the link's own CLASS is unsupported (e.g. `image`, a photo attachment —
   * every endpoint could be perfectly mapped and it would STILL be dropped)
   * vs. a supported class whose endpoint didn't resolve to a real VsmNode
   * (§14.4's actual "missing relationship" case). Absent when `supported`. */
  unsupportedReason?: 'class' | 'missing_endpoint'
  connection: VsmConnection | null
}

/** `nodeIdByKey` maps a SimVSM node `key` to the VsmNode id it was mapped to
 * — only contains keys for SUPPORTED nodes (see streams.ts), so a lookup
 * miss here already means "endpoint was an unsupported/annotation node". */
export function mapSimVsmLink(link: SimVsmParsedLink, nodeIdByKey: ReadonlyMap<string, string>, idFactory: () => string): LinkMapOutcome {
  const entry = classifyLink(link.simvsmClass)
  if (!entry || !entry.supported) {
    return {
      simvsmKey: link.key,
      simvsmClass: link.simvsmClass,
      supported: false,
      labelDe: entry?.labelDe ?? 'Nicht unterstützte Verbindungsart',
      reasonDe: entry?.reasonDe ?? `Unbekannte Verbindungsart "${link.simvsmClass}" — im Mapping-Register nicht erfasst.`,
      unsupportedReason: 'class',
      connection: null,
    }
  }

  const fromNodeId = nodeIdByKey.get(link.fromKey)
  const toNodeId = nodeIdByKey.get(link.toKey)
  if (!fromNodeId || !toNodeId) {
    return {
      simvsmKey: link.key,
      simvsmClass: link.simvsmClass,
      supported: false,
      reasonDe: 'Verbindung verweist auf einen nicht übernommenen Knoten (z. B. eine Anmerkung) — fehlende Beziehung.',
      unsupportedReason: 'missing_endpoint',
      connection: null,
    }
  }

  const connection: VsmConnection = {
    id: idFactory(),
    fromNodeId,
    toNodeId,
  }
  if (entry.targetKind) connection.kind = entry.targetKind
  if (entry.targetKind === 'information' && link.text) connection.frequency = link.text
  else if (link.text) connection.label = link.text

  return {
    simvsmKey: link.key,
    simvsmClass: link.simvsmClass,
    supported: true,
    connection,
  }
}
