-- Audit-final v3 - wire the FK columns currently exposed via Drizzle
-- relations() but missing actual Postgres constraints. relations() only
-- configures relational query JOINs; it does NOT install constraints, so
-- a service that writes interest_id='nonexistent' faces no DB rejection
-- and downstream null-tolerant joins silently misbehave.
--
-- All adds are idempotent (DO blocks swallow duplicate_object) and use
-- the NOT VALID + VALIDATE pattern so the brief table-lock phase is
-- decoupled from the slow row-scan validation. If validation fails for
-- a constraint the migration aborts before later constraints land - a
-- prod operator can clean the dirty row(s) and re-run.
--
-- Cascade rule:
--   nullable column → ON DELETE SET NULL    (orphan tolerance)
--   notNull column  → ON DELETE RESTRICT    (force callers to clean up)
-- All audit-listed columns happen to be nullable so they get SET NULL.
--
-- Refs: docs/audit-comprehensive-2026-05-05.md HIGH §10 (auditor-C3 Issue 1).

-- ─── Pre-cleanup: invoices.billing_entity_id non-empty ──────────────────────
-- The previous schema declared notNull().default(''), so historical rows
-- may carry empty strings. The CHECK constraint added below would reject
-- the migration on a dirty table. Backfill from clientName when present
-- so the resolver downstream can still find a usable handle, otherwise
-- fall back to the row id (which gives the operator a unique marker to
-- audit later). This UPDATE is a no-op on a clean DB.

UPDATE invoices
SET billing_entity_id = COALESCE(NULLIF(client_name, ''), id)
WHERE billing_entity_id = '';

-- ─── documents ─────────────────────────────────────────────────────────────

DO $$ BEGIN
  ALTER TABLE documents
    ADD CONSTRAINT documents_interest_id_fkey
      FOREIGN KEY (interest_id) REFERENCES interests(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE documents VALIDATE CONSTRAINT documents_interest_id_fkey;

DO $$ BEGIN
  ALTER TABLE documents
    ADD CONSTRAINT documents_yacht_id_fkey
      FOREIGN KEY (yacht_id) REFERENCES yachts(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE documents VALIDATE CONSTRAINT documents_yacht_id_fkey;

DO $$ BEGIN
  ALTER TABLE documents
    ADD CONSTRAINT documents_company_id_fkey
      FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE documents VALIDATE CONSTRAINT documents_company_id_fkey;

DO $$ BEGIN
  ALTER TABLE documents
    ADD CONSTRAINT documents_reservation_id_fkey
      FOREIGN KEY (reservation_id) REFERENCES berth_reservations(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE documents VALIDATE CONSTRAINT documents_reservation_id_fkey;

-- ─── files ─────────────────────────────────────────────────────────────────

DO $$ BEGIN
  ALTER TABLE files
    ADD CONSTRAINT files_yacht_id_fkey
      FOREIGN KEY (yacht_id) REFERENCES yachts(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE files VALIDATE CONSTRAINT files_yacht_id_fkey;

DO $$ BEGIN
  ALTER TABLE files
    ADD CONSTRAINT files_company_id_fkey
      FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE files VALIDATE CONSTRAINT files_company_id_fkey;

-- ─── interests ─────────────────────────────────────────────────────────────

DO $$ BEGIN
  ALTER TABLE interests
    ADD CONSTRAINT interests_yacht_id_fkey
      FOREIGN KEY (yacht_id) REFERENCES yachts(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE interests VALIDATE CONSTRAINT interests_yacht_id_fkey;

-- ─── reminders ─────────────────────────────────────────────────────────────

DO $$ BEGIN
  ALTER TABLE reminders
    ADD CONSTRAINT reminders_interest_id_fkey
      FOREIGN KEY (interest_id) REFERENCES interests(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE reminders VALIDATE CONSTRAINT reminders_interest_id_fkey;

DO $$ BEGIN
  ALTER TABLE reminders
    ADD CONSTRAINT reminders_berth_id_fkey
      FOREIGN KEY (berth_id) REFERENCES berths(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE reminders VALIDATE CONSTRAINT reminders_berth_id_fkey;

-- ─── berth_waiting_list ────────────────────────────────────────────────────

DO $$ BEGIN
  ALTER TABLE berth_waiting_list
    ADD CONSTRAINT berth_waiting_list_yacht_id_fkey
      FOREIGN KEY (yacht_id) REFERENCES yachts(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE berth_waiting_list VALIDATE CONSTRAINT berth_waiting_list_yacht_id_fkey;

-- ─── form_submissions ──────────────────────────────────────────────────────

DO $$ BEGIN
  ALTER TABLE form_submissions
    ADD CONSTRAINT form_submissions_interest_id_fkey
      FOREIGN KEY (interest_id) REFERENCES interests(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE form_submissions VALIDATE CONSTRAINT form_submissions_interest_id_fkey;

-- ─── Polymorphic CHECK round 2 ──────────────────────────────────────────────
-- 0036 covered yachts.current_owner_type and invoices.billing_entity_type.
-- These two discriminators were missed and remain free-text.

DO $$ BEGIN
  ALTER TABLE yacht_ownership_history
    ADD CONSTRAINT yacht_ownership_history_owner_type_chk
      CHECK (owner_type IN ('client', 'company')) NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE yacht_ownership_history VALIDATE CONSTRAINT yacht_ownership_history_owner_type_chk;

DO $$ BEGIN
  ALTER TABLE document_sends
    ADD CONSTRAINT document_sends_document_kind_chk
      CHECK (document_kind IN ('berth_pdf', 'brochure')) NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE document_sends VALIDATE CONSTRAINT document_sends_document_kind_chk;

-- ─── invoices.billing_entity_id sanity check ───────────────────────────────
-- The pre-cleanup at the top of this migration backfilled empty strings
-- to clientName (or row id), so the VALIDATE step is now safe.

DO $$ BEGIN
  ALTER TABLE invoices
    ADD CONSTRAINT invoices_billing_entity_id_nonempty_chk
      CHECK (billing_entity_id <> '') NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE invoices VALIDATE CONSTRAINT invoices_billing_entity_id_nonempty_chk;

-- ─── clients.merged_into_client_id self-FK ─────────────────────────────────
-- Already nullable; populated when a client is soft-merged into another.

DO $$ BEGIN
  ALTER TABLE clients
    ADD CONSTRAINT clients_merged_into_client_id_fkey
      FOREIGN KEY (merged_into_client_id) REFERENCES clients(id) ON DELETE SET NULL NOT VALID;
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
ALTER TABLE clients VALIDATE CONSTRAINT clients_merged_into_client_id_fkey;
