-- V77: timeline domain foundation (Zeitstrahl) — curated timeline events.
-- Forward-only, additive DDL. No rollback script: rollback requires manual DROP TABLE
-- (timeline_event_documents, timeline_event_persons, then timeline_events). See ADR-040.
--
-- The date block (event_date / date_precision / event_date_end) mirrors documents' so events
-- and letters share one rendering path. Two divergences from documents are INTENTIONAL and
-- enforced here in Postgres (ADR-040):
--   1. The RANGE rule is a strict biconditional (event_date_end non-null IFF RANGE), unlike
--      documents' open-ended ranges — a curated event always has a known, closed end.
--   2. date_precision <> 'UNKNOWN' — only OCR-inferred letters are ever undated; a curated
--      event always has at least a year. SEASON and APPROX stay legal (Sommer/ca. 1914).

CREATE TABLE timeline_events (
    id             UUID         NOT NULL DEFAULT gen_random_uuid(),
    title          VARCHAR(255) NOT NULL,
    type           VARCHAR(16)  NOT NULL,
    event_date     DATE         NOT NULL,
    date_precision VARCHAR(16)  NOT NULL DEFAULT 'YEAR',
    event_date_end DATE,
    description    TEXT,
    created_by     UUID         NOT NULL,
    created_at     TIMESTAMP,
    updated_by     UUID         NOT NULL,
    updated_at     TIMESTAMP,
    version        BIGINT,
    CONSTRAINT pk_timeline_events PRIMARY KEY (id),
    -- event_date_end is non-null IFF precision is RANGE (both directions).
    CONSTRAINT chk_timeline_event_range
        CHECK ((date_precision = 'RANGE') = (event_date_end IS NOT NULL)),
    -- Curated events are never undated. Forbids exactly UNKNOWN — every other
    -- DatePrecision value (DAY, MONTH, SEASON, YEAR, RANGE, APPROX) stays legal.
    CONSTRAINT chk_timeline_event_precision
        CHECK (date_precision <> 'UNKNOWN')
);

-- Join table: events ↔ persons involved.
CREATE TABLE timeline_event_persons (
    timeline_event_id UUID NOT NULL,
    person_id         UUID NOT NULL,
    CONSTRAINT pk_timeline_event_persons PRIMARY KEY (timeline_event_id, person_id),
    CONSTRAINT fk_tep_event
        FOREIGN KEY (timeline_event_id) REFERENCES timeline_events(id) ON DELETE CASCADE,
    CONSTRAINT fk_tep_person
        FOREIGN KEY (person_id) REFERENCES persons(id) ON DELETE CASCADE
);

-- Join table: events ↔ supporting letters.
CREATE TABLE timeline_event_documents (
    timeline_event_id UUID NOT NULL,
    document_id       UUID NOT NULL,
    CONSTRAINT pk_timeline_event_documents PRIMARY KEY (timeline_event_id, document_id),
    CONSTRAINT fk_ted_event
        FOREIGN KEY (timeline_event_id) REFERENCES timeline_events(id) ON DELETE CASCADE,
    CONSTRAINT fk_ted_document
        FOREIGN KEY (document_id) REFERENCES documents(id) ON DELETE CASCADE
);

-- Indexes added up-front (avoid the V62 FK-index retrofit debt): the two query columns plus
-- the inverse-side FK columns. timeline_event_id needs no extra index on either join table —
-- it is the leading column of the composite PK, so the PK index already serves those lookups.
CREATE INDEX idx_timeline_events_event_date ON timeline_events (event_date);
CREATE INDEX idx_timeline_events_type ON timeline_events (type);
CREATE INDEX idx_timeline_event_persons_person_id ON timeline_event_persons (person_id);
CREATE INDEX idx_timeline_event_documents_document_id ON timeline_event_documents (document_id);
