/**
 * Composition profile schema (ADR 013).
 *
 * A composition profile is the single authoritative description of "what this
 * deployment is" — branding, feature flags, integration adapters, modes.
 * Customer-specific behaviour is selected by profile, never by `if (tenant.isBmw)`
 * checks in core code (ADR 010 R1 / R2).
 *
 * Phase 0 ships the skeleton; later phases extend the shape additively.
 * Boot fails fast if the active profile does not validate (Zod safeParse).
 */

import { z } from "zod";

export const BrandingProfileSchema = z.object({
  /** Display name shown in UI chrome (e.g. "SupplierDev", "Acme Supplier Portal"). */
  productName: z.string().min(1),
  /** Asset key for the logo; resolved by the branding loader. */
  logoAssetKey: z.string().min(1),
  /** Primary palette identifier; resolved by the theme registry. Customer-specific palettes use "custom" and are wired by the customer adapter. */
  paletteKey: z.enum(["default", "neutral", "custom"]),
  /** Optional support footer text. */
  supportFooter: z.string().optional(),
});

export const FeatureFlagsSchema = z.object({
  /** Owner console (cross-tenant management). */
  ownerConsole: z.boolean(),
  /** Strong-auth enforcement (TOTP / WebAuthn / customer SSO). */
  strongAuth: z.boolean(),
  /** Demo data seeds visible to non-demo tenants. */
  demoSeeds: z.boolean(),
  /** Wertstrom (VSM) module. */
  wertstrom: z.boolean(),
  /** OEE module. */
  oee: z.boolean(),
  /** LSC workshop module. */
  lscWorkshop: z.boolean(),
  /** Capture (input) of work_mode ("Arbeitsort") on assignment create/edit/bulk-edit. Display/export of already-stored work_mode data is unaffected (FB-36 follow-up). */
  workModeCapture: z.boolean(),
  /** "Berater-Auslastung (letzte 90 Tage)" report section — dashboard render + PDF/PPTX export (FB-41). */
  consultantLoadReport: z.boolean(),
  /** QAF→Value-Stream import (QVS, KAR-970/KAR-968). `false` everywhere until
   * corpus validation lands (P6/P7, see reports/qaf-value-stream-architecture.md
   * E5) — P1 only ships the flag + the underlying pure lib/qaf-value-stream
   * module, no UI reads this yet. */
  qafValueStream: z.boolean(),
  /** KAR-993: Lieferanten-Benchmark (zwei Angebote verschiedener Lieferanten,
   * matching-freier Kennzahlen-Vergleich). */
  qafSupplierBenchmark: z.boolean(),
  /** Copilot-Exporte (Demo-067 C, KAR-982): DOCX/XLSX-Exporte je Modul
   * (Fabrikanalyse/QAF-Vergleich/Wertstrom) + Gesamtprojekt, mit
   * AI-Instruction-Block, gedacht zum Weiterverarbeiten in einem externen
   * LLM-Tool. Gate lebt in `lib/copilot-export` (copilotExportsGate) +
   * jeder der vier Export-Server-Actions; UI-Buttons sind zusätzlich
   * client-seitig ausgeblendet, wenn `false`. */
  copilotExports: z.boolean(),
  /** Wertstrom-Szenarien-UI (A9, KAR-878/KAR-986, PR #353 Review-Fix F2):
   * "Soll-Zustand erstellen" (Toolbar-Button, Listen-/Editor-Badge,
   * `POST /api/wertstrom/[id]/duplicate`). `false` in every profile —
   * CAPABILITY-MATRIX.md scopes P2 to the Szenarien-DATENMODELL only
   * (`parent_value_stream_id`/`scenario_kind` columns, Zod, Engine) and
   * explicitly assigns the A9-UI (Erstellen/Delta-Vergleich/
   * Abweichungs-Panel) to P5, which the matrix's own flag-mandatory list
   * requires a flag for. The data-model fields stay unflagged/additive —
   * only the create-UI + its route are gated. Gate lives in
   * `lib/api/feature-gates.ts` (`wertstromScenariosGate`, same shape as
   * `copilotExportsGate`); UI reads this flag via a
   * server-resolved prop (`wertstromScenariosEnabled`), same convention as
   * `copilotExportsEnabled`. */
  wertstromScenarios: z.boolean(),
  /** Wertstrom Quick-Start-Wizard + Auto-Layout + Timeline-Leiter v2 (P3,
   * KAR-878/KAR-986, CAPABILITY-MATRIX.md A1/A2/A4 — "das UX-Herz"). `false`
   * in every profile — Phasenplan-Pflicht für P3 (Capability-Matrix
   * "Implementierungs-Phasenplan": "Feature-Flags für P3/P5/P6"), same
   * convention as `wertstromScenarios` above (gate lives in
   * `lib/api/feature-gates.ts`, `wertstromUxV2Gate`; UI reads a
   * server-resolved `wertstromUxV2Enabled` prop). Gates: the wizard entry
   * point (Startseiten-Button "Neu mit Assistent"), the "Automatisch
   * anordnen" editor button, and the Timeline-Leiter v2 (VA/NVA-Treppe +
   * DLZ + PCE) that replaces the old 1-Prozentbalken. The underlying pure
   * libs (`components/wertstrom/vsm-auto-layout.ts`,
   * `vsm-wizard-logic.ts`) are NOT gated — additive, inert without UI. */
  wertstromUxV2: z.boolean(),
  /** Wertstrom SimVSM-Import-Adapter (P6, KAR-878/KAR-986, execution-prompt
   * §14, Capability-Matrix A16): optional multi-file SimVSM `.json`/`.svg`
   * import behind a two-stage preview/confirm flow
   * (`POST /api/wertstrom/import/preview` + `/confirm`). `false` in every
   * profile — Phasenplan-Pflicht (Capability-Matrix "Feature-Flags für
   * P3/P5/P6"), same convention as `wertstromScenarios`/`wertstromUxV2`
   * (gate lives in `lib/api/feature-gates.ts`, `wertstromSimvsmImportGate`;
   * UI reads a server-resolved `wertstromSimvsmImportEnabled` prop). Gates
   * both import routes and the "SimVSM importieren" entry point on the
   * Wertstrom-Liste. SupplierPulse does not depend on this for normal use
   * (execution-prompt §14 preamble) — see lib/simvsm-import/README.md. */
  wertstromSimvsmImport: z.boolean(),
  /** Per-customer experimental flags. Free-form record; consumers must read defensively. */
  experimental: z.record(z.string(), z.boolean()).default({}),
});

/**
 * Integration adapter slots.
 *
 * Customer-specific adapters (e.g. an enterprise SSO, an internal mail gateway,
 * a proprietary observability sink) MUST NOT appear as enum values here. They
 * are selected via the generic `"custom"` value and resolved by the active
 * customer adapter under `lib/customers/<id>/adapters/...` (ADR 010 / ADR 015).
 */
export const IntegrationsProfileSchema = z.object({
  /** Identity / auth mode. */
  auth: z.enum(["supabase", "oidc", "saml", "azure-ad", "okta", "custom"]),
  /** Observability mode. */
  observability: z.enum(["console", "otlp", "datadog", "grafana-cloud", "custom"]),
  /** Object storage mode. */
  storage: z.enum(["supabase-storage", "s3", "azure-blob", "custom"]),
  /** Background queue mode. */
  queue: z.enum(["none", "bullmq", "pg-boss", "sqs", "azure-servicebus", "vercel-queues", "custom"]),
  /** Outbound email mode. */
  email: z.enum(["none", "resend", "ses", "sendgrid", "smtp", "custom"]),
  /** Support / ticketing mode. */
  support: z.enum(["none", "email-only", "jira", "servicenow", "freshservice", "custom"]),
  /** AI provider mode. */
  ai: z.enum(["none", "openai", "anthropic", "azure-openai", "bedrock", "on-prem-llm", "custom"]).default("none"),
  /** Per-tenant default datastore placement. */
  datastore: z.enum(["supabase", "postgres", "cloud-sql", "custom"]).default("supabase"),
});

export const CompositionProfileSchema = z
  .object({
    /** Profile identifier used by APP_PROFILE env var. */
    name: z.string().regex(/^[a-z0-9_-]+$/, "Profile name must be lowercase alphanumeric / dash / underscore."),
    /** Free-form description for operators. */
    description: z.string().min(1),
    /** Whether this profile may be used in production. `_template` is false. */
    productionReady: z.boolean(),
    branding: BrandingProfileSchema,
    features: FeatureFlagsSchema,
    integrations: IntegrationsProfileSchema,
  })
  .strict();

export type BrandingProfile = z.infer<typeof BrandingProfileSchema>;
export type FeatureFlags = z.infer<typeof FeatureFlagsSchema>;
export type IntegrationsProfile = z.infer<typeof IntegrationsProfileSchema>;
export type CompositionProfile = z.infer<typeof CompositionProfileSchema>;

export function validateProfile(input: unknown): { ok: true; profile: CompositionProfile } | { ok: false; error: string } {
  const parsed = CompositionProfileSchema.safeParse(input);
  if (parsed.success) return { ok: true, profile: parsed.data };
  const issues = parsed.error.issues.map((i) => `  - ${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
  return { ok: false, error: `Composition profile failed validation:\n${issues}` };
}
