-- Reminders & follow-ups — a real tickler/task model tied to the fundraising grid.
--
-- ADDITIVE + REVERSIBLE (CLAUDE.md guardrail #3): one new table + indexes; nothing
-- existing is touched. Until now the only follow-up surfaces were the grid's binary
-- `follow_up` checkbox (no date, owner, or status) and communications.next_action_date
-- (tied to a single logged comm). This gives investors first-class reminders with a due
-- date, status lifecycle, assignee, and provenance — the foundation for "who needs a
-- follow-up?" queries, the daily digest's due/overdue section, and (later) bot-proposed
-- reminders behind the Matrix approval gate.
--
-- investor_id is a LOGICAL foreign key to fundraising_investors(id) — deliberately NOT a
-- declared SQLite FOREIGN KEY, matching opportunities.fundraising_investor_id (migration
-- 0005). fundraising_investors rows are upserted by source_row_id on every grid save with
-- a STABLE id (so the link survives saves), but a row dropped from the grid is DELETEd —
-- there is nothing to cascade, and reconcile_grid_reminders() cancels the orphans on the
-- next save (the pipeline reconciler's twin). investor_name is denormalized so a reminder
-- stays readable in history even after its grid row is gone. investor_id is nullable: a
-- reminder can be a standalone team task not tied to any investor.
--
-- contact_id is an optional logical FK to contacts(id) (the specific person). assignee_id
-- is a logical ref to users(id) (NULL = team-wide). created_by holds a users.id OR a
-- non-user sentinel ('bot'/'automation'), so it is plain TEXT with no FK.
CREATE TABLE IF NOT EXISTS reminders (
    id            TEXT PRIMARY KEY,
    investor_id   TEXT,                                   -- logical FK -> fundraising_investors.id (NULL = standalone task)
    investor_name TEXT,                                   -- denormalized; survives grid-row deletion
    contact_id    TEXT,                                   -- optional logical FK -> contacts.id
    title         TEXT NOT NULL,
    details       TEXT,
    due_date      TEXT,                                   -- ISO date 'YYYY-MM-DD' (or datetime)
    status        TEXT NOT NULL DEFAULT 'open',           -- open | done | snoozed | cancelled
    snoozed_until TEXT,
    assignee_id   TEXT,                                   -- logical ref -> users.id; NULL = team-wide
    created_by    TEXT,                                   -- users.id, or 'bot' / 'automation'
    source        TEXT NOT NULL DEFAULT 'human',          -- human | bot | automation
    completed_at  TEXT,
    created_at    TEXT DEFAULT (datetime('now')),
    updated_at    TEXT DEFAULT (datetime('now')),
    deleted_at    TEXT
);

CREATE INDEX IF NOT EXISTS idx_reminders_investor ON reminders(investor_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_reminders_status   ON reminders(status)      WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_reminders_due      ON reminders(due_date)    WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_reminders_assignee ON reminders(assignee_id) WHERE deleted_at IS NULL;
