-- migrate:no-foreign-keys
--
-- §22.13 / §22.4 — fold project_id into the slug-keyed PRIMARY KEY / UNIQUE
-- constraints that migration 026 deliberately left global, so a *second*
-- project can hold an entry with the same slug as the first. M1 (026) added
-- project_id additively (no rebuild); this is the rebuild that activates
-- project #2, enumerated in 026's header.
--
-- SQLite can't ALTER a PK/UNIQUE in place, so each table is rebuilt by the
-- official procedure: create `<t>__new` with the new constraint, copy, DROP
-- the live table, rename `<t>__new` -> `<t>`, recreate its indexes. FK
-- enforcement is OFF for the whole file (the `migrate:no-foreign-keys` marker
-- above tells the runner to toggle it and run foreign_key_check after).
--
-- DROP-the-live-table (rather than rename-live-to-__old) is deliberate: SQLite
-- rewrites child FK references when you RENAME a *referenced* table, so we drop
-- the old cached_rfcs (allowed with FK off) and rename the temp in. cached_rfcs
-- is rebuilt FIRST so rfc_collaborators / contribution_requests can re-point
-- their FK at its new composite (project_id, slug) key.

-- ── cached_rfcs: PRIMARY KEY (slug) -> (project_id, slug) ──────────────────
CREATE TABLE cached_rfcs__new (
    slug                TEXT NOT NULL,
    title               TEXT NOT NULL,
    state               TEXT NOT NULL CHECK (state IN ('super-draft', 'active', 'withdrawn', 'retired')),
    rfc_id              TEXT,
    repo                TEXT,
    proposed_by         TEXT,
    proposed_at         TEXT,
    graduated_at        TEXT,
    graduated_by        TEXT,
    owners_json         TEXT NOT NULL DEFAULT '[]',
    arbiters_json       TEXT NOT NULL DEFAULT '[]',
    tags_json           TEXT NOT NULL DEFAULT '[]',
    body                TEXT,
    body_sha            TEXT,
    last_main_commit_at TEXT,
    last_entry_commit_at TEXT,
    updated_at          TEXT NOT NULL DEFAULT (datetime('now')),
    models_json         TEXT,
    funder_login        TEXT,
    proposed_use_case   TEXT,
    project_id          TEXT NOT NULL DEFAULT 'default',
    unreviewed          INTEGER NOT NULL DEFAULT 0,
    reviewed_at         TEXT,
    reviewed_by         TEXT,
    PRIMARY KEY (project_id, slug)
);
INSERT INTO cached_rfcs__new SELECT * FROM cached_rfcs;
DROP TABLE cached_rfcs;
ALTER TABLE cached_rfcs__new RENAME TO cached_rfcs;
CREATE INDEX idx_cached_rfcs_state ON cached_rfcs (state);
CREATE INDEX idx_cached_rfcs_last_active ON cached_rfcs (
    COALESCE(last_main_commit_at, last_entry_commit_at) DESC
);
CREATE INDEX idx_cached_rfcs_project ON cached_rfcs(project_id);

-- ── rfc_invitations: FK rfc_slug -> cached_rfcs(slug) becomes composite ────
-- (no key change of its own, but its single-column FK to cached_rfcs is now a
-- mismatch against the composite PK, so it must be rebuilt too). Rebuilt after
-- cached_rfcs (its FK target) and before the two tables that FK rfc_invitations.
CREATE TABLE rfc_invitations__new (
    id                      INTEGER PRIMARY KEY AUTOINCREMENT,
    rfc_slug                TEXT NOT NULL,
    inviter_user_id         INTEGER REFERENCES users(id) ON DELETE SET NULL,
    invitee_email           TEXT NOT NULL,
    role_in_rfc             TEXT NOT NULL CHECK (role_in_rfc IN ('contributor', 'discussant')),
    status                  TEXT NOT NULL DEFAULT 'pending'
        CHECK (status IN ('pending', 'accepted', 'revoked', 'expired')),
    token                   TEXT NOT NULL,
    expires_at              TEXT NOT NULL,
    created_at              TEXT NOT NULL DEFAULT (datetime('now')),
    accepted_at             TEXT,
    accepted_by_user_id     INTEGER REFERENCES users(id) ON DELETE SET NULL,
    project_id              TEXT NOT NULL DEFAULT 'default',
    FOREIGN KEY (project_id, rfc_slug) REFERENCES cached_rfcs(project_id, slug) ON DELETE CASCADE
);
INSERT INTO rfc_invitations__new SELECT * FROM rfc_invitations;
DROP TABLE rfc_invitations;
ALTER TABLE rfc_invitations__new RENAME TO rfc_invitations;
CREATE UNIQUE INDEX idx_rfc_invitations_token ON rfc_invitations (token);
CREATE INDEX idx_rfc_invitations_rfc_status ON rfc_invitations (rfc_slug, status);
CREATE INDEX idx_rfc_invitations_email_status ON rfc_invitations (invitee_email, status);

-- ── cached_branches: UNIQUE (rfc_slug, branch_name) -> +project_id ─────────
CREATE TABLE cached_branches__new (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    rfc_slug        TEXT NOT NULL,
    branch_name     TEXT NOT NULL,
    head_sha        TEXT,
    state           TEXT NOT NULL DEFAULT 'open' CHECK (state IN ('open', 'closed', 'deleted')),
    pinned          INTEGER NOT NULL DEFAULT 0,
    created_at      TEXT NOT NULL DEFAULT (datetime('now')),
    last_commit_at  TEXT,
    closed_at       TEXT,
    project_id      TEXT NOT NULL DEFAULT 'default',
    UNIQUE (project_id, rfc_slug, branch_name)
);
INSERT INTO cached_branches__new SELECT * FROM cached_branches;
DROP TABLE cached_branches;
ALTER TABLE cached_branches__new RENAME TO cached_branches;
CREATE INDEX idx_cached_branches_rfc ON cached_branches (rfc_slug, state);

-- ── branch_visibility: UNIQUE (rfc_slug, branch_name) -> +project_id ───────
CREATE TABLE branch_visibility__new (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    rfc_slug        TEXT NOT NULL,
    branch_name     TEXT NOT NULL,
    read_public     INTEGER NOT NULL DEFAULT 1,
    contribute_mode TEXT NOT NULL DEFAULT 'just-me' CHECK (contribute_mode IN ('just-me', 'specific', 'any-contributor')),
    project_id      TEXT NOT NULL DEFAULT 'default',
    UNIQUE (project_id, rfc_slug, branch_name)
);
INSERT INTO branch_visibility__new SELECT * FROM branch_visibility;
DROP TABLE branch_visibility;
ALTER TABLE branch_visibility__new RENAME TO branch_visibility;

-- ── branch_contribute_grants: UNIQUE (rfc_slug, branch_name, grantee) -> +pid
CREATE TABLE branch_contribute_grants__new (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    rfc_slug        TEXT NOT NULL,
    branch_name     TEXT NOT NULL,
    grantee_user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    granted_by      INTEGER NOT NULL REFERENCES users(id) ON DELETE SET NULL,
    granted_at      TEXT NOT NULL DEFAULT (datetime('now')),
    project_id      TEXT NOT NULL DEFAULT 'default',
    UNIQUE (project_id, rfc_slug, branch_name, grantee_user_id)
);
INSERT INTO branch_contribute_grants__new SELECT * FROM branch_contribute_grants;
DROP TABLE branch_contribute_grants;
ALTER TABLE branch_contribute_grants__new RENAME TO branch_contribute_grants;
CREATE INDEX idx_grants_lookup ON branch_contribute_grants (rfc_slug, branch_name);
CREATE INDEX idx_grants_grantee ON branch_contribute_grants (grantee_user_id);

-- ── stars: UNIQUE (user_id, rfc_slug) -> +project_id ───────────────────────
CREATE TABLE stars__new (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id     INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    rfc_slug    TEXT NOT NULL,
    starred_at  TEXT NOT NULL DEFAULT (datetime('now')),
    project_id  TEXT NOT NULL DEFAULT 'default',
    UNIQUE (project_id, user_id, rfc_slug)
);
INSERT INTO stars__new SELECT * FROM stars;
DROP TABLE stars;
ALTER TABLE stars__new RENAME TO stars;
CREATE INDEX idx_stars_user ON stars (user_id);
CREATE INDEX idx_stars_rfc ON stars (rfc_slug);

-- ── watches: UNIQUE (user_id, rfc_slug) -> +project_id ─────────────────────
CREATE TABLE watches__new (
    id                      INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id                 INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    rfc_slug                TEXT NOT NULL,
    state                   TEXT NOT NULL CHECK (state IN ('watching', 'following', 'muted')),
    set_by                  TEXT NOT NULL CHECK (set_by IN ('auto', 'explicit')),
    set_at                  TEXT NOT NULL DEFAULT (datetime('now')),
    last_participation_at   TEXT,
    project_id              TEXT NOT NULL DEFAULT 'default',
    UNIQUE (project_id, user_id, rfc_slug)
);
INSERT INTO watches__new SELECT * FROM watches;
DROP TABLE watches;
ALTER TABLE watches__new RENAME TO watches;
CREATE INDEX idx_watches_user ON watches (user_id);
CREATE INDEX idx_watches_rfc ON watches (rfc_slug);
CREATE INDEX idx_watches_decay ON watches (state, last_participation_at);

-- ── pr_seen: UNIQUE (user_id, rfc_slug, pr_number) -> +project_id ──────────
CREATE TABLE pr_seen__new (
    id                      INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id                 INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    rfc_slug                TEXT NOT NULL,
    pr_number               INTEGER NOT NULL,
    last_seen_commit_sha    TEXT,
    last_seen_message_id    INTEGER REFERENCES thread_messages(id) ON DELETE SET NULL,
    seen_at                 TEXT NOT NULL DEFAULT (datetime('now')),
    project_id              TEXT NOT NULL DEFAULT 'default',
    UNIQUE (project_id, user_id, rfc_slug, pr_number)
);
INSERT INTO pr_seen__new SELECT * FROM pr_seen;
DROP TABLE pr_seen;
ALTER TABLE pr_seen__new RENAME TO pr_seen;

-- ── branch_chat_seen: UNIQUE (user_id, rfc_slug, branch_name) -> +project_id
CREATE TABLE branch_chat_seen__new (
    id                      INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id                 INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    rfc_slug                TEXT NOT NULL,
    branch_name             TEXT NOT NULL,
    last_seen_message_id    INTEGER REFERENCES thread_messages(id) ON DELETE SET NULL,
    seen_at                 TEXT NOT NULL DEFAULT (datetime('now')),
    project_id              TEXT NOT NULL DEFAULT 'default',
    UNIQUE (project_id, user_id, rfc_slug, branch_name)
);
INSERT INTO branch_chat_seen__new SELECT * FROM branch_chat_seen;
DROP TABLE branch_chat_seen;
ALTER TABLE branch_chat_seen__new RENAME TO branch_chat_seen;

-- ── funder_consents: PRIMARY KEY (user_id, rfc_slug) -> +project_id ────────
CREATE TABLE funder_consents__new (
    user_id     INTEGER NOT NULL,
    rfc_slug    TEXT    NOT NULL,
    created_at  TEXT    NOT NULL DEFAULT (datetime('now')),
    project_id  TEXT    NOT NULL DEFAULT 'default',
    PRIMARY KEY (project_id, user_id, rfc_slug),
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
INSERT INTO funder_consents__new SELECT * FROM funder_consents;
DROP TABLE funder_consents;
ALTER TABLE funder_consents__new RENAME TO funder_consents;
CREATE INDEX idx_funder_consents_slug ON funder_consents (rfc_slug);

-- ── rfc_collaborators: UNIQUE idx (rfc_slug, user_id) -> +project_id;
--     FK rfc_slug -> cached_rfcs(slug) becomes composite (project_id, rfc_slug)
CREATE TABLE rfc_collaborators__new (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    rfc_slug        TEXT NOT NULL,
    user_id         INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    role_in_rfc     TEXT NOT NULL CHECK (role_in_rfc IN ('contributor', 'discussant')),
    invitation_id   INTEGER REFERENCES rfc_invitations(id) ON DELETE SET NULL,
    created_at      TEXT NOT NULL DEFAULT (datetime('now')),
    project_id      TEXT NOT NULL DEFAULT 'default',
    FOREIGN KEY (project_id, rfc_slug) REFERENCES cached_rfcs(project_id, slug) ON DELETE CASCADE
);
INSERT INTO rfc_collaborators__new SELECT * FROM rfc_collaborators;
DROP TABLE rfc_collaborators;
ALTER TABLE rfc_collaborators__new RENAME TO rfc_collaborators;
CREATE UNIQUE INDEX idx_rfc_collaborators_unique ON rfc_collaborators (project_id, rfc_slug, user_id);
CREATE INDEX idx_rfc_collaborators_user ON rfc_collaborators (user_id);

-- ── contribution_requests: UNIQUE idx (rfc_slug, requester) WHERE pending
--     -> +project_id; FK rfc_slug -> cached_rfcs(slug) becomes composite.
CREATE TABLE contribution_requests__new (
    id                  INTEGER PRIMARY KEY AUTOINCREMENT,
    rfc_slug            TEXT NOT NULL,
    requester_user_id   INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    matched_term        TEXT NOT NULL,
    who_i_am            TEXT NOT NULL,
    why                 TEXT NOT NULL,
    use_case            TEXT,
    status              TEXT NOT NULL DEFAULT 'pending'
                            CHECK (status IN ('pending', 'accepted', 'declined')),
    created_at          TEXT NOT NULL DEFAULT (datetime('now')),
    decided_at          TEXT,
    decided_by_user_id  INTEGER REFERENCES users(id) ON DELETE SET NULL,
    invitation_id       INTEGER REFERENCES rfc_invitations(id) ON DELETE SET NULL,
    notification_id     INTEGER REFERENCES notifications(id) ON DELETE SET NULL,
    project_id          TEXT NOT NULL DEFAULT 'default',
    FOREIGN KEY (project_id, rfc_slug) REFERENCES cached_rfcs(project_id, slug) ON DELETE CASCADE
);
INSERT INTO contribution_requests__new SELECT * FROM contribution_requests;
DROP TABLE contribution_requests;
ALTER TABLE contribution_requests__new RENAME TO contribution_requests;
CREATE INDEX idx_contribution_requests_rfc ON contribution_requests(rfc_slug, status);
CREATE INDEX idx_contribution_requests_requester ON contribution_requests(requester_user_id, status);
CREATE UNIQUE INDEX idx_contribution_requests_one_open
    ON contribution_requests(project_id, rfc_slug, requester_user_id)
    WHERE status = 'pending';

-- ── proposed_use_cases: UNIQUE (scope, pr_number) -> +project_id ───────────
CREATE TABLE proposed_use_cases__new (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    scope           TEXT NOT NULL CHECK (scope IN ('rfc', 'pr')),
    rfc_slug        TEXT NOT NULL,
    pr_number       INTEGER NOT NULL,
    use_case        TEXT NOT NULL,
    created_at      TEXT NOT NULL DEFAULT (datetime('now')),
    project_id      TEXT NOT NULL DEFAULT 'default',
    UNIQUE (project_id, scope, pr_number)
);
INSERT INTO proposed_use_cases__new SELECT * FROM proposed_use_cases;
DROP TABLE proposed_use_cases;
ALTER TABLE proposed_use_cases__new RENAME TO proposed_use_cases;
CREATE INDEX idx_proposed_use_cases_lookup ON proposed_use_cases (scope, pr_number);
CREATE INDEX idx_proposed_use_cases_slug ON proposed_use_cases (scope, rfc_slug);
