-- Move person-delete referential integrity from application code into the database (#684).
--
-- Before this migration, PersonService.deletePerson nulled documents.sender_id and removed
-- document_receivers rows in Java before deleting the person, because the two V1 FKs into
-- persons had no ON DELETE behaviour. Any other delete path (a future endpoint, a manual
-- psql, a batch job) could still orphan rows or 500. This migration makes the database the
-- single source of truth so a person delete is safe from every path.
--
-- Cascade boundary: the cascade stays STRICTLY at the join/reference layer and NEVER reaches
-- documents rows — a cascade into documents would destroy historical letters. sender_id is
-- SET NULL (documents.senderText preserves the raw textual attribution); the receiver join
-- row and the @-mention sidecar row are dropped.
--
-- No NOT VALID + VALIDATE two-step: these tables are small (thousands of rows → sub-second
-- ACCESS EXCLUSIVE lock). Do NOT copy this drop-and-recreate pattern onto a large table.
--
-- Not audit-logged: a DB ON DELETE cascade runs below AuditService — a known, accepted trade.
-- The person-delete action itself is still logged at the service layer.

-- documents.sender_id → ON DELETE SET NULL (deleted sender clears the link; the document survives).
ALTER TABLE public.documents
    DROP CONSTRAINT fkl5xhww7es3b4um01vmly4y18m,
    ADD CONSTRAINT fkl5xhww7es3b4um01vmly4y18m
        FOREIGN KEY (sender_id) REFERENCES public.persons(id) ON DELETE SET NULL;

-- document_receivers.person_id → ON DELETE CASCADE (drop the join row), the symmetric
-- completion of V14, which added the same to the document_id side of this table.
ALTER TABLE public.document_receivers
    DROP CONSTRAINT fkcg7r68qvosqricx1betgrlt7s,
    ADD CONSTRAINT fkcg7r68qvosqricx1betgrlt7s
        FOREIGN KEY (person_id) REFERENCES public.persons(id) ON DELETE CASCADE;

-- Soft reference fix: transcription_block_mentioned_persons.person_id was a UUID with no FK
-- (V56), so deleting a person left dangling mention rows. Give it a real FK with CASCADE.
-- This reverses V56's deliberate "no FK on person_id" choice — that comment is now historical
-- but is intentionally left untouched, because editing an already-applied migration changes its
-- Flyway checksum and would fail validateOnMigrate in prod. ADR-032 is the authoritative record.
-- Clean up pre-existing orphans first — production likely holds dangling rows because the old
-- deletePerson never cleaned mention rows, and the ADD CONSTRAINT validation scan fails on them.
-- A DO block with RAISE NOTICE surfaces the purge count: Flyway runs each statement via JDBC
-- and discards a trailing SELECT's result set, so a "SELECT count(*)" would log nothing.
DO $$
DECLARE removed int;
BEGIN
    DELETE FROM transcription_block_mentioned_persons m
    WHERE NOT EXISTS (SELECT 1 FROM persons p WHERE p.id = m.person_id);
    GET DIAGNOSTICS removed = ROW_COUNT;
    RAISE NOTICE 'V71 orphaned_mention_rows_removed=%', removed;
END $$;

ALTER TABLE public.transcription_block_mentioned_persons
    ADD CONSTRAINT fk_tbmp_person
        FOREIGN KEY (person_id) REFERENCES public.persons(id) ON DELETE CASCADE;
