-- ============================================================================
-- REFERRAL / INSTROOM DOMAIN
-- ============================================================================
-- Created: 2026-07-20
-- Source: docs/datamodel/deelmodellen/model-instroom.md (20 entiteiten),
--   docs/datamodel/feitenmodellen/feitenmodel-instroom.md, besluiten B21-B30.
--
-- Design principles carried over from the model documents:
-- - referral_case has NO status column — the current state is derived from
--   the event timeline (signal_case_assignment/screening_activity/
--   case_information_request/care_acceptance_decision/case_withdrawal/
--   case_consolidation). See model-instroom.md §5. Application code (or a
--   read-model view, per the UX review) computes "actuele stand", not this
--   schema.
-- - "vervangt"-relations (care_acceptance_decision, professional_referral,
--   municipal_care_assignment) are enforced unique-if-set (partial unique
--   index) so the chain can never fork.
-- - `medewerker`/beslisser references point at the existing `practitioners`
--   table (already used by the prototype screening/intake schema).
-- - `decision_authority_id` on care_acceptance_decision is left nullable
--   for now: the target table for decision authority does not exist yet
--   (bevoegdheidsronde, B16/B33). The model calls it "verplicht"; enforcing
--   NOT NULL today would make every insert impossible. Tighten once that
--   ronde delivers a real authority table.
-- ============================================================================

-- ============================================================================
-- referral_request
-- ============================================================================
CREATE TABLE referral_request (
  id                    UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  person_id             UUID REFERENCES person(id) ON DELETE RESTRICT,
  person_identified_at  TIMESTAMPTZ,
  person_identified_by  UUID REFERENCES practitioners(id),
  initiated_at          TIMESTAMPTZ NOT NULL,
  initiator_type        TEXT NOT NULL,             -- waardelijst initiator_type
  referrer_id           UUID REFERENCES referrer(id),
  requested_scope       TEXT NOT NULL,
  presenting_need_text  TEXT NOT NULL,

  created_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at            TIMESTAMPTZ,

  CONSTRAINT referral_request_person_identification CHECK (
    (person_id IS NULL AND person_identified_at IS NULL AND person_identified_by IS NULL)
    OR (person_id IS NOT NULL AND person_identified_at IS NOT NULL AND person_identified_by IS NOT NULL)
  )
);

COMMENT ON TABLE referral_request IS 'model-instroom.md §2.1. person_id optioneel: crisisaanmelding met onbekende identiteit (B26) — geen placeholder-persoon, de koppeling is een eigen feit.';

ALTER TABLE referral_request ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON referral_request FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_referral_request_updated_at BEFORE UPDATE ON referral_request FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- referral_submission
-- ============================================================================
CREATE TABLE referral_submission (
  id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  received_at       TIMESTAMPTZ NOT NULL,
  channel           TEXT NOT NULL,                 -- waardelijst submission_channel
  source_reference  TEXT,                          -- vrije tekst of naam verwijzer; "onbekend" toegestaan
  recorded_by       UUID REFERENCES practitioners(id),
  raw_note          TEXT,

  created_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at        TIMESTAMPTZ
);

COMMENT ON TABLE referral_submission IS 'model-instroom.md §2.2. Nooit overschreven door een latere aanvulling — een aanvulling is een nieuwe submission.';

ALTER TABLE referral_submission ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON referral_submission FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_referral_submission_updated_at BEFORE UPDATE ON referral_submission FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- submission_document
-- ============================================================================
CREATE TABLE submission_document (
  id                  UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  submission_id       UUID NOT NULL REFERENCES referral_submission(id) ON DELETE CASCADE,
  document_type       TEXT NOT NULL,                -- waardelijst document_type
  document_reference  UUID NOT NULL,                -- documentopslag

  created_at          TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at          TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at          TIMESTAMPTZ
);

CREATE INDEX idx_submission_document_submission ON submission_document(submission_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE submission_document IS 'model-instroom.md §2.3.';

ALTER TABLE submission_document ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON submission_document FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_submission_document_updated_at BEFORE UPDATE ON submission_document FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- submission_request_link
-- ============================================================================
CREATE TABLE submission_request_link (
  id                  UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  submission_id       UUID NOT NULL REFERENCES referral_submission(id) ON DELETE CASCADE,
  referral_request_id UUID NOT NULL REFERENCES referral_request(id) ON DELETE CASCADE,
  established_at      TIMESTAMPTZ NOT NULL,

  created_at          TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at          TIMESTAMPTZ,

  UNIQUE (submission_id, referral_request_id)
);

CREATE INDEX idx_submission_request_link_request ON submission_request_link(referral_request_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE submission_request_link IS 'model-instroom.md §2.4. "representeert" vs "vult_aan" is niet opgeslagen — af te leiden als vroegste established_at per referral_request_id.';

ALTER TABLE submission_request_link ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON submission_request_link FOR ALL USING (auth.role() = 'authenticated');

-- ============================================================================
-- submission_duplicate_assessment
-- ============================================================================
CREATE TABLE submission_duplicate_assessment (
  id                          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  submission_id               UUID NOT NULL REFERENCES referral_submission(id) ON DELETE CASCADE,
  duplicate_of_submission_id  UUID NOT NULL REFERENCES referral_submission(id) ON DELETE CASCADE,
  assessed_by                 UUID NOT NULL REFERENCES practitioners(id),
  assessed_at                 TIMESTAMPTZ NOT NULL,
  reason                      TEXT NOT NULL,

  created_at                  TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at                  TIMESTAMPTZ,

  CONSTRAINT submission_duplicate_not_self CHECK (submission_id <> duplicate_of_submission_id)
);

COMMENT ON TABLE submission_duplicate_assessment IS 'model-instroom.md §2.5. Niet-destructief: beide submissions blijven bestaan.';

ALTER TABLE submission_duplicate_assessment ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON submission_duplicate_assessment FOR ALL USING (auth.role() = 'authenticated');

-- ============================================================================
-- referral_case
-- ============================================================================
CREATE TABLE referral_case (
  id                        UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  person_id                 UUID REFERENCES person(id) ON DELETE RESTRICT,
  person_identified_at      TIMESTAMPTZ,
  person_identified_by      UUID REFERENCES practitioners(id),
  opened_at                 TIMESTAMPTZ NOT NULL,
  presenting_need_summary   TEXT NOT NULL,
  legal_framework           TEXT NOT NULL,          -- waardelijst wettelijk_kader
  zpm_referral_type         TEXT,                   -- waardelijst zpm_verwijstype
  gp_informed_at            DATE,

  created_at                TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at                TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at                TIMESTAMPTZ,

  CONSTRAINT referral_case_person_identification CHECK (
    (person_id IS NULL AND person_identified_at IS NULL AND person_identified_by IS NULL)
    OR (person_id IS NOT NULL AND person_identified_at IS NOT NULL AND person_identified_by IS NOT NULL)
  )
);

COMMENT ON TABLE referral_case IS 'model-instroom.md §2.6. Geen statusveld — zie §5 aldaar en de opmerking bovenaan dit bestand. legal_framework/zpm_referral_type/gp_informed_at hersteld van het oudere AANMELDING (B21-B27).';

ALTER TABLE referral_case ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON referral_case FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_referral_case_updated_at BEFORE UPDATE ON referral_case FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- Now that referral_case exists: wire the consent scope FK from the person/client migration
ALTER TABLE consent
  ADD CONSTRAINT consent_scope_referral_case_fk FOREIGN KEY (scope_referral_case_id) REFERENCES referral_case(id) ON DELETE SET NULL;

-- ============================================================================
-- submission_case_assignment
-- ============================================================================
CREATE TABLE submission_case_assignment (
  id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  submission_id     UUID NOT NULL REFERENCES referral_submission(id) ON DELETE CASCADE,
  referral_case_id  UUID NOT NULL REFERENCES referral_case(id) ON DELETE CASCADE,
  assigned_at       TIMESTAMPTZ NOT NULL,
  assigned_by       UUID NOT NULL REFERENCES practitioners(id),
  reason            TEXT,

  created_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at        TIMESTAMPTZ,

  UNIQUE (submission_id, referral_case_id)
);

CREATE INDEX idx_submission_case_assignment_case ON submission_case_assignment(referral_case_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE submission_case_assignment IS 'model-instroom.md §2.7 (hernoemd van signal_case_assignment). Toewijzing is een gebeurtenis, geen overschrijfbaar veld.';

ALTER TABLE submission_case_assignment ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON submission_case_assignment FOR ALL USING (auth.role() = 'authenticated');

-- ============================================================================
-- request_case_link
-- ============================================================================
CREATE TABLE request_case_link (
  id                    UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_request_id   UUID NOT NULL REFERENCES referral_request(id) ON DELETE CASCADE,
  referral_case_id      UUID NOT NULL REFERENCES referral_case(id) ON DELETE CASCADE,
  since_date            DATE NOT NULL,
  reason                TEXT,

  created_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at            TIMESTAMPTZ,

  UNIQUE (referral_request_id, referral_case_id)
);

COMMENT ON TABLE request_case_link IS 'model-instroom.md §2.8. reason verplicht (applicatieniveau) zodra een request aan >1 case gekoppeld is.';

ALTER TABLE request_case_link ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON request_case_link FOR ALL USING (auth.role() = 'authenticated');

-- ============================================================================
-- case_consolidation
-- ============================================================================
CREATE TABLE case_consolidation (
  id                    UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  primary_case_id       UUID NOT NULL REFERENCES referral_case(id) ON DELETE RESTRICT,
  related_case_id       UUID NOT NULL REFERENCES referral_case(id) ON DELETE RESTRICT,
  overlap_assessed_at   TIMESTAMPTZ,
  designated_at         TIMESTAMPTZ NOT NULL,
  designated_by         UUID NOT NULL REFERENCES practitioners(id),
  reason                TEXT NOT NULL,

  created_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at            TIMESTAMPTZ,

  CONSTRAINT case_consolidation_no_self CHECK (primary_case_id <> related_case_id)
);

-- een case kan hoogstens één keer de niet-leidende rol vervullen
CREATE UNIQUE INDEX idx_case_consolidation_related_unique ON case_consolidation(related_case_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE case_consolidation IS 'model-instroom.md §2.9 (hernoemd van access_case_consolidation). Geen speciale decision_authority vereist (administratieve correctie). Transitieve cykels niet uitgesloten op schemaniveau — applicatieverantwoordelijkheid.';

ALTER TABLE case_consolidation ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON case_consolidation FOR ALL USING (auth.role() = 'authenticated');

-- ============================================================================
-- screening_activity
-- ============================================================================
CREATE TABLE screening_activity (
  id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_case_id  UUID NOT NULL REFERENCES referral_case(id) ON DELETE CASCADE,
  performed_at      TIMESTAMPTZ NOT NULL,
  activity_type     TEXT NOT NULL,          -- waardelijst screening_activity_type
  performed_by      UUID NOT NULL REFERENCES practitioners(id),
  notes             TEXT,
  funded            BOOLEAN NOT NULL DEFAULT false,

  created_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at        TIMESTAMPTZ
);

CREATE INDEX idx_screening_activity_case ON screening_activity(referral_case_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE screening_activity IS 'model-instroom.md §2.10. Directe koppeling aan referral_case — de aparte "screening"-groeperingsentiteit is vervallen (reviewronde 19 juli).';

ALTER TABLE screening_activity ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON screening_activity FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_screening_activity_updated_at BEFORE UPDATE ON screening_activity FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- case_information_request
-- ============================================================================
CREATE TABLE case_information_request (
  id                          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_case_id            UUID NOT NULL REFERENCES referral_case(id) ON DELETE CASCADE,
  requested_at                TIMESTAMPTZ NOT NULL,
  requested_by                UUID NOT NULL REFERENCES practitioners(id),
  requested_information       TEXT NOT NULL,
  resolved_by_submission_id   UUID REFERENCES referral_submission(id),

  created_at                  TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at                  TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at                  TIMESTAMPTZ
);

CREATE UNIQUE INDEX idx_case_information_request_resolved_submission ON case_information_request(resolved_by_submission_id) WHERE resolved_by_submission_id IS NOT NULL AND deleted_at IS NULL;
CREATE INDEX idx_case_information_request_case ON case_information_request(referral_case_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE case_information_request IS 'model-instroom.md §2.11. Geen besluituitkomst en geen statusfase (B21/vraag 5) — een gedateerd gebeurtenisfeit; kan zich ook ná een eerder besluit voordoen tijdens heroverweging.';

ALTER TABLE case_information_request ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON case_information_request FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_case_information_request_updated_at BEFORE UPDATE ON case_information_request FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- care_acceptance_decision
-- ============================================================================
CREATE TABLE care_acceptance_decision (
  id                     UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_case_id       UUID NOT NULL REFERENCES referral_case(id) ON DELETE RESTRICT,
  decided_at             TIMESTAMPTZ NOT NULL,
  decided_by             UUID NOT NULL REFERENCES practitioners(id),
  decision_authority_id  UUID,                    -- ref decision_authority — tabel volgt uit bevoegdheidsronde (B16); tijdelijk geen FK/NOT NULL
  content_match          BOOLEAN NOT NULL,
  capacity_available     BOOLEAN,
  program_context        TEXT,                    -- waardelijst care_program of vrije tekst
  decision_outcome       TEXT NOT NULL,            -- waardelijst decision_outcome
  follow_up_route        TEXT NOT NULL,            -- waardelijst follow_up_route
  rationale              TEXT,
  replaces_decision_id   UUID REFERENCES care_acceptance_decision(id),
  replacement_reason     TEXT,

  created_at             TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at             TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at             TIMESTAMPTZ,

  CONSTRAINT care_acceptance_decision_outcome_check CHECK (decision_outcome IN ('geaccepteerd', 'afgewezen')),
  CONSTRAINT care_acceptance_decision_rationale_required CHECK (
    decision_outcome <> 'afgewezen' OR (rationale IS NOT NULL AND length(trim(rationale)) > 0)
  ),
  CONSTRAINT care_acceptance_decision_replacement_reason_required CHECK (
    replaces_decision_id IS NULL OR (replacement_reason IS NOT NULL AND length(trim(replacement_reason)) > 0)
  ),
  CONSTRAINT care_acceptance_decision_no_self_replace CHECK (replaces_decision_id <> id)
);

-- vervangt-keten kan nooit vertakken (B23 / reviewronde 19 juli, kritieke bevinding)
CREATE UNIQUE INDEX idx_care_acceptance_decision_replaces_unique ON care_acceptance_decision(replaces_decision_id) WHERE replaces_decision_id IS NOT NULL AND deleted_at IS NULL;
CREATE INDEX idx_care_acceptance_decision_case ON care_acceptance_decision(referral_case_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE care_acceptance_decision IS 'model-instroom.md §2.12. Geen apart voorafgaand screeningsadvies (B21). Concurrency bij gelijktijdige heroverwegingen (SELECT ... FOR UPDATE op de keten-tail) is applicatieverantwoordelijkheid.';

ALTER TABLE care_acceptance_decision ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON care_acceptance_decision FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_care_acceptance_decision_updated_at BEFORE UPDATE ON care_acceptance_decision FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- case_withdrawal
-- ============================================================================
CREATE TABLE case_withdrawal (
  id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_case_id  UUID NOT NULL REFERENCES referral_case(id) ON DELETE CASCADE,
  withdrawn_at      TIMESTAMPTZ NOT NULL,
  recorded_by       UUID NOT NULL REFERENCES practitioners(id),
  note              TEXT,

  created_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at        TIMESTAMPTZ
);

CREATE INDEX idx_case_withdrawal_case ON case_withdrawal(referral_case_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE case_withdrawal IS 'model-instroom.md §2.13. Geen beslisbevoegdheid vereist; kan op elk moment, ook ná een positief besluit (B24).';

ALTER TABLE case_withdrawal ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON case_withdrawal FOR ALL USING (auth.role() = 'authenticated');

-- ============================================================================
-- professional_referral
-- ============================================================================
CREATE TABLE professional_referral (
  id                    UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_request_id   UUID NOT NULL REFERENCES referral_request(id) ON DELETE RESTRICT,
  referrer_id           UUID NOT NULL REFERENCES referrer(id),
  referral_date         DATE NOT NULL,
  echelon               TEXT,                      -- waardelijst echelon
  suspected_condition   TEXT,
  is_readmission        BOOLEAN NOT NULL DEFAULT false,
  replaces_referral_id  UUID REFERENCES professional_referral(id),
  replacement_reason    TEXT,

  created_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at            TIMESTAMPTZ,

  CONSTRAINT professional_referral_replacement_reason_required CHECK (
    replaces_referral_id IS NULL OR (replacement_reason IS NOT NULL AND length(trim(replacement_reason)) > 0)
  ),
  CONSTRAINT professional_referral_no_self_replace CHECK (replaces_referral_id <> id)
);

CREATE UNIQUE INDEX idx_professional_referral_replaces_unique ON professional_referral(replaces_referral_id) WHERE replaces_referral_id IS NOT NULL AND deleted_at IS NULL;
CREATE INDEX idx_professional_referral_request ON professional_referral(referral_request_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE professional_referral IS 'model-instroom.md §2.14. Correctie/aanvulling = nieuw, vervangend record, geen nieuw request (was open punt 1, opgelost).';

ALTER TABLE professional_referral ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON professional_referral FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_professional_referral_updated_at BEFORE UPDATE ON professional_referral FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- municipal_care_assignment
-- ============================================================================
CREATE TABLE municipal_care_assignment (
  id                    UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_request_id   UUID NOT NULL REFERENCES referral_request(id) ON DELETE RESTRICT,
  legal_framework       TEXT NOT NULL,            -- waardelijst municipal_legal_framework
  municipality_code     TEXT NOT NULL,
  assignment_number     TEXT NOT NULL,
  product_category      TEXT NOT NULL,            -- waardelijst municipal_product_category
  product_code          TEXT NOT NULL,
  volume                NUMERIC NOT NULL,
  unit                  TEXT NOT NULL,            -- waardelijst municipal_product_unit
  frequency             TEXT NOT NULL,
  start_date            DATE NOT NULL,
  end_date              DATE,
  issued_at             TIMESTAMPTZ NOT NULL,
  replaces_assignment_id UUID REFERENCES municipal_care_assignment(id),
  replacement_reason    TEXT,

  created_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at            TIMESTAMPTZ,

  CONSTRAINT municipal_care_assignment_replacement_reason_required CHECK (
    replaces_assignment_id IS NULL OR (replacement_reason IS NOT NULL AND length(trim(replacement_reason)) > 0)
  ),
  CONSTRAINT municipal_care_assignment_no_self_replace CHECK (replaces_assignment_id <> id)
);

CREATE UNIQUE INDEX idx_municipal_care_assignment_replaces_unique ON municipal_care_assignment(replaces_assignment_id) WHERE replaces_assignment_id IS NOT NULL AND deleted_at IS NULL;
CREATE UNIQUE INDEX idx_municipal_care_assignment_number ON municipal_care_assignment(municipality_code, assignment_number) WHERE deleted_at IS NULL;

COMMENT ON TABLE municipal_care_assignment IS 'model-instroom.md §2.15 (voorstel, juridisch onderzoek 19 juli). Naast, niet in plaats van professional_referral (Jeugdwet kent een eigen professionele verwijsroute).';

ALTER TABLE municipal_care_assignment ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON municipal_care_assignment FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_municipal_care_assignment_updated_at BEFORE UPDATE ON municipal_care_assignment FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- legal_mandate
-- ============================================================================
CREATE TABLE legal_mandate (
  id                            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_case_id              UUID NOT NULL REFERENCES referral_case(id) ON DELETE RESTRICT,
  mandate_type                  TEXT NOT NULL,      -- waardelijst mandate_type
  decision_reference            TEXT NOT NULL,
  decided_by_role               TEXT NOT NULL,      -- waardelijst mandate_decider_role
  decided_at                    TIMESTAMPTZ NOT NULL,
  medical_statement_reference   UUID,               -- documentopslag
  effectuated_at                TIMESTAMPTZ NOT NULL,
  valid_from                    TIMESTAMPTZ NOT NULL,
  valid_until                   TIMESTAMPTZ,

  created_at                    TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at                    TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at                    TIMESTAMPTZ,

  CONSTRAINT legal_mandate_type_check CHECK (mandate_type IN ('crisismaatregel', 'zorgmachtiging')),
  CONSTRAINT legal_mandate_medical_statement_required CHECK (
    mandate_type <> 'crisismaatregel' OR medical_statement_reference IS NOT NULL
  )
);

CREATE INDEX idx_legal_mandate_case ON legal_mandate(referral_case_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE legal_mandate IS 'model-instroom.md §2.16 (voorstel, juridisch onderzoek 19 juli). Geen vervangt-relatie: een crisismaatregel die overgaat in een zorgmachtiging is een nieuw mandaat.';

ALTER TABLE legal_mandate ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON legal_mandate FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_legal_mandate_updated_at BEFORE UPDATE ON legal_mandate FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- crisis_encounter_note
-- ============================================================================
CREATE TABLE crisis_encounter_note (
  id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_case_id  UUID NOT NULL REFERENCES referral_case(id) ON DELETE CASCADE,
  occurred_at       TIMESTAMPTZ NOT NULL,
  recorded_by       UUID NOT NULL REFERENCES practitioners(id),
  fact_type         TEXT NOT NULL,          -- waardelijst crisis_fact_type
  description       TEXT NOT NULL,
  structured_value  JSONB,

  created_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at        TIMESTAMPTZ
);

CREATE INDEX idx_crisis_encounter_note_case ON crisis_encounter_note(referral_case_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE crisis_encounter_note IS 'model-instroom.md §2.17 (voorstel). Werkt al zonder geïdentificeerde persoon. 14-dagen-identificatienudge hangt aan referral_request.person_identified_at IS NULL, geen constraint hier.';

ALTER TABLE crisis_encounter_note ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON crisis_encounter_note FOR ALL USING (auth.role() = 'authenticated');

-- ============================================================================
-- clinical_care_episode
-- ============================================================================
CREATE TABLE clinical_care_episode (
  id                                    UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  originating_decision_id               UUID REFERENCES care_acceptance_decision(id) ON DELETE RESTRICT,
  originating_mandate_id                UUID REFERENCES legal_mandate(id) ON DELETE RESTRICT,
  started_at                            TIMESTAMPTZ NOT NULL,
  ended_at                              TIMESTAMPTZ,
  end_reason                            TEXT,                -- waardelijst episode_end_reason
  possible_continuation_of_episode_id   UUID REFERENCES clinical_care_episode(id),

  created_at                            TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at                            TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at                            TIMESTAMPTZ,

  CONSTRAINT clinical_care_episode_origin_xor CHECK (
    (originating_decision_id IS NOT NULL AND originating_mandate_id IS NULL)
    OR (originating_decision_id IS NULL AND originating_mandate_id IS NOT NULL)
  ),
  CONSTRAINT clinical_care_episode_end_reason_required CHECK (
    ended_at IS NULL OR end_reason IS NOT NULL
  ),
  CONSTRAINT clinical_care_episode_no_self_continuation CHECK (possible_continuation_of_episode_id <> id)
);

CREATE UNIQUE INDEX idx_clinical_care_episode_decision ON clinical_care_episode(originating_decision_id) WHERE originating_decision_id IS NOT NULL AND deleted_at IS NULL;
CREATE UNIQUE INDEX idx_clinical_care_episode_mandate ON clinical_care_episode(originating_mandate_id) WHERE originating_mandate_id IS NOT NULL AND deleted_at IS NULL;

COMMENT ON TABLE clinical_care_episode IS 'model-instroom.md §2.18 (alleen ontstaan/einde — volledig episodemodel is een ander deelgebied). XOR: ontstaat óf uit een acceptatiebesluit óf uit een mandaat. possible_continuation_of_episode_id is een zorginhoudelijke aanwijzing, GEEN NZa-trajectnummertoets.';

ALTER TABLE clinical_care_episode ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON clinical_care_episode FOR ALL USING (auth.role() = 'authenticated');
CREATE TRIGGER update_clinical_care_episode_updated_at BEFORE UPDATE ON clinical_care_episode FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- case_urgency_assessment
-- ============================================================================
CREATE TABLE case_urgency_assessment (
  id                UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  referral_case_id  UUID NOT NULL REFERENCES referral_case(id) ON DELETE CASCADE,
  assessed_at       TIMESTAMPTZ NOT NULL,
  assessed_by       UUID NOT NULL REFERENCES practitioners(id),
  assessed_in_role  TEXT NOT NULL,          -- waardelijst urgency_assessor_role
  urgency_level     TEXT NOT NULL,          -- waardelijst urgency_level

  created_at        TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at        TIMESTAMPTZ
);

CREATE INDEX idx_case_urgency_assessment_case ON case_urgency_assessment(referral_case_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE case_urgency_assessment IS 'model-instroom.md §2.19. Herhaalbaar, laatste assessed_at geldt; geen vervangt-relatie (lagere inzet dan een acceptatiebesluit).';

ALTER TABLE case_urgency_assessment ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON case_urgency_assessment FOR ALL USING (auth.role() = 'authenticated');

-- ============================================================================
-- episode_team_involvement (minimale, voorlopige hook — zie besluitenlog §10 punt 3)
-- ============================================================================
CREATE TABLE episode_team_involvement (
  id                          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  clinical_care_episode_id    UUID NOT NULL REFERENCES clinical_care_episode(id) ON DELETE CASCADE,
  team_reference              TEXT NOT NULL,     -- vrije tekst; geen Team-entiteit vóór de zorgteam-ronde
  involved_since               TIMESTAMPTZ NOT NULL,
  recorded_by                  UUID NOT NULL REFERENCES practitioners(id),

  created_at                   TIMESTAMPTZ NOT NULL DEFAULT now(),
  deleted_at                   TIMESTAMPTZ
);

CREATE INDEX idx_episode_team_involvement_episode ON episode_team_involvement(clinical_care_episode_id) WHERE deleted_at IS NULL;

COMMENT ON TABLE episode_team_involvement IS 'model-instroom.md §2.20. Bewust minimaal — geen rollen, geen bevoegdheid, geen individueel lidmaatschap. Wordt vervangen/geabsorbeerd door het volledige zorgteam-model (besluitenlog §10 punt 3).';

ALTER TABLE episode_team_involvement ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Enable all for authenticated users" ON episode_team_involvement FOR ALL USING (auth.role() = 'authenticated');
