-- Identity model (per ADR-0026 PR 1).
--
-- Person golden record + User portal-account overlay (1-to-0-or-1)
-- + UserScope (the table behind the ADR-0025 scope axis). Distinct
-- from `user_directory_entries` (ADR-0020 sign-in cache, renamed in
-- the previous migration) — those keep their role; these are new.
--
-- No seed data — the test-tenant scope rows ship in ADR-0026 PR 2
-- via `prisma/seed.ts`, after this schema is in place.

-- CreateTable
CREATE TABLE "persons" (
    "id" UUID NOT NULL,
    "first_name" TEXT NOT NULL,
    "last_name" TEXT NOT NULL,
    "email" TEXT,
    "source" TEXT NOT NULL,
    "external_id" TEXT,
    "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMPTZ(6) NOT NULL,

    CONSTRAINT "persons_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "users" (
    "id" UUID NOT NULL,
    "person_id" UUID NOT NULL,
    "entra_oid" TEXT NOT NULL,
    "tenant_id" TEXT NOT NULL,
    "last_sign_in_at" TIMESTAMPTZ(6),
    "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMPTZ(6) NOT NULL,

    CONSTRAINT "users_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "user_scopes" (
    "id" UUID NOT NULL,
    "user_id" UUID NOT NULL,
    "kind" TEXT NOT NULL,
    "value" TEXT NOT NULL DEFAULT '',
    "source" TEXT NOT NULL,
    "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "expires_at" TIMESTAMPTZ(6),

    CONSTRAINT "user_scopes_pkey" PRIMARY KEY ("id")
);

-- Person indexes
CREATE INDEX "persons_source_idx" ON "persons"("source");

CREATE INDEX "persons_external_id_idx" ON "persons"("external_id");

CREATE INDEX "persons_email_idx" ON "persons"("email");

-- User indexes — both unique constraints back btree indexes.
CREATE UNIQUE INDEX "users_person_id_key" ON "users"("person_id");

CREATE UNIQUE INDEX "users_entra_oid_key" ON "users"("entra_oid");

-- UserScope indexes — the unique constraint backs the composite,
-- the plain index supports the read-by-userId hot path on sign-in.
CREATE UNIQUE INDEX "user_scopes_user_id_kind_value_key" ON "user_scopes"("user_id", "kind", "value");

CREATE INDEX "user_scopes_user_id_idx" ON "user_scopes"("user_id");

-- Foreign keys.
--
-- User.person_id is REQUIRED → ON DELETE RESTRICT (Prisma default for
-- required relations). Removing a Person with a portal User must be
-- an explicit two-step in the admin path; never an accidental cascade.
ALTER TABLE "users" ADD CONSTRAINT "users_person_id_fkey"
    FOREIGN KEY ("person_id") REFERENCES "persons"("id")
    ON DELETE RESTRICT ON UPDATE CASCADE;

-- UserScope.user_id has explicit `onDelete: Cascade` in the Prisma
-- schema — revoking a User wipes their scope rows in one delete,
-- which is the desired admin-UI semantic (deactivating an account
-- should not leave dangling authorisation rows).
ALTER TABLE "user_scopes" ADD CONSTRAINT "user_scopes_user_id_fkey"
    FOREIGN KEY ("user_id") REFERENCES "users"("id")
    ON DELETE CASCADE ON UPDATE CASCADE;
