/**
 * QAF→Wertstrom import preview (QVS-P2, KAR-971, architecture.md §2/§4).
 *
 * Orchestrates the P1 pure functions (assessManufacturingCapability,
 * mapQafRowsToVsmNodes, buildDefaultTitle) against a real qaf_file via
 * qaf-source.ts, and adds the duplicate-import hint (duplicates.ts).
 * Read-only — safe to call repeatedly (e.g. re-opening the same dialog).
 */

import type { SupabaseClient } from '@supabase/supabase-js'
import type { VsmConnection, VsmNode } from '@/lib/vsm-types'
import type { CapabilityAssessment, ExcludedRow, MissingFieldReason, QvsWarning } from './types'
import { assessManufacturingCapability } from './manufacturing-capability'
import { MAPPING_VERSION } from './mapper'
import { buildDefaultTitle, type DefaultTitleParts } from './naming'
import { loadQafSourceRows, mapAndFingerprint, type QafSourceRows, type QvsFileLevelContext } from './qaf-source'
import { findExistingImports, type QvsExistingImport, type FindExistingImportsResult } from './duplicates'
import { loadMultiQafVariantContext, type QvsVariantContext } from './multi-qaf-context'

export interface QvsImportPreview {
  qafFileId: string
  projectId: string
  /** `qaf_file.original_file_name` (qaf-source.ts QafFileRef) — the Preview
   * dialog's "Quelle (Dateiname)" line (ux-flow.md §5) needs this for
   * display; P2 already loads it into `QafSourceRows.qafFile` but never
   * surfaced it on the returned preview. Display-only, never used for any
   * business decision (file identity/matching stays on `qafFileId`/hash). */
  sourceFileName: string
  /** See qaf-source.ts computePreviewToken doc — echoed back unchanged by a
   * confirmed creation (creation.ts QvsPreviewConfirmation.previewToken). */
  previewToken: string
  mappingVersion: string
  parserVersion: string | null
  suggestedTitle: string
  capability: CapabilityAssessment
  /** Every node carries `qafSource.rowIndex` — a future "abwählbare
   * Schritte" UI (P3) references steps by that, not by `node.id` (node ids
   * are freshly randomized per call, not stable across preview→confirm). */
  nodes: VsmNode[]
  connections: VsmConnection[]
  excludedRows: ExcludedRow[]
  missingFieldReasons: MissingFieldReason[]
  warnings: QvsWarning[]
  duplicates: QvsExistingImport[]
  /** Review-Fix 3: true when the duplicate-check query itself failed (e.g.
   * `value_stream_imports` missing) — `duplicates` is `[]` in that case too,
   * but a future P3 UI MUST show "Duplikat-Check nicht verfügbar" rather
   * than reading an empty `duplicates` array as a confirmed "0 duplicates". */
  duplicateCheckDegraded: boolean
  /** QVS-P4 — sum_planned_capacity/sum_lot_size (Datei-Ebene, see
   * qaf-source.ts QvsFileLevelContext doc). Both fields null when the source
   * file predates this PR or did not carry these labels. */
  fileLevelContext: QvsFileLevelContext
  /** QVS-P4 (gap-analysis G5, ux-flow.md §4) — non-null ONLY when this file
   * is the standard (`alt`) side of a `multi_qaf_variant_vs_standard`
   * comparison AND that comparison's container side has ≥1 active variant.
   * `null` (the overwhelming common case) means "no Varianten-Sektion to
   * show" — never an error; a genuine lookup failure surfaces as
   * `{variants: [], degraded: true}` instead of `null` (see
   * multi-qaf-context.ts QvsVariantContext doc) so the dialog can
   * distinguish "not applicable" from "couldn't check". */
  variantContext: QvsVariantContext | null
}

export interface BuildPreviewOptions {
  /** Supplier/project/variant parts for buildDefaultTitle. Caller already
   * has these (project row, variant selection) — passing them in keeps this
   * service from needing its own extra join for display-only data. */
  titleParts?: DefaultTitleParts
  /** QVS-P4 — precomputed by buildQafValueStreamPreview (the one DB-wired
   * caller that can actually query qaf_comparison/qaf_file for it);
   * buildPreviewFromRows itself stays DB-access-free (preview.real-files.test.ts
   * exercises it directly against real-corpus rows, no database). Omitted
   * entirely (not just `undefined`) means "not checked" — real callers
   * always pass it explicitly once wired; test callers that don't care about
   * Multi-QAF at all can simply omit it and get `variantContext: null`. */
  variantContext?: QvsVariantContext | null
}

/**
 * DB-wired entrypoint: fetches qaf_file + qaf_manufacturing_step (RLS-scoped)
 * and existing-import duplicates, then delegates to buildPreviewFromRows.
 * Returns `null` for "not found / not visible to caller" (see qaf-source.ts)
 * — never a distinguishable "forbidden" (architecture.md §9, no existence
 * leak).
 */
export async function buildQafValueStreamPreview(
  supabase: SupabaseClient,
  qafFileId: string,
  options: BuildPreviewOptions = {},
): Promise<QvsImportPreview | null> {
  const source = await loadQafSourceRows(supabase, qafFileId)
  if (!source) return null

  const [duplicatesResult, variantContext] = await Promise.all([
    findExistingImports(supabase, {
      projectId: source.qafFile.projectId,
      fileHash: source.qafFile.fileHash,
    }),
    loadMultiQafVariantContext(supabase, qafFileId),
  ])

  return buildPreviewFromRows(source, duplicatesResult, { ...options, variantContext })
}

/**
 * Pure(-ish) assembly: capability + mapper + title + previewToken, given
 * already-loaded source rows and an already-resolved duplicates result
 * (Review-Fix 3: `{ items, degraded }`, never a bare array — `degraded` must
 * survive into `QvsImportPreview.duplicateCheckDegraded` rather than being
 * silently dropped here). No DB access of its own — kept separate from
 * buildQafValueStreamPreview so it can be exercised directly against
 * real-corpus-parsed QAFRow[] without a database
 * (internal/__tests__/preview.real-files.test.ts, same discipline as
 * mapper.real-files.test.ts).
 */
export function buildPreviewFromRows(
  source: QafSourceRows,
  duplicatesResult: FindExistingImportsResult,
  options: BuildPreviewOptions = {},
): QvsImportPreview {
  const capability = assessManufacturingCapability(source.rows)
  const { mapped, previewToken } = mapAndFingerprint(source)

  return {
    qafFileId: source.qafFile.id,
    projectId: source.qafFile.projectId,
    sourceFileName: source.qafFile.originalFileName,
    previewToken,
    mappingVersion: MAPPING_VERSION,
    parserVersion: source.qafFile.parserVersion,
    suggestedTitle: buildDefaultTitle(options.titleParts ?? {}),
    capability,
    nodes: mapped.nodes,
    connections: mapped.connections,
    excludedRows: mapped.excludedRows,
    missingFieldReasons: mapped.missingFieldReasons,
    warnings: mapped.warnings,
    duplicates: duplicatesResult.items,
    duplicateCheckDegraded: duplicatesResult.degraded,
    fileLevelContext: source.qafFile.fileLevelContext,
    variantContext: options.variantContext ?? null,
  }
}
