// src/lib/db/admin-schema.ts — SuperAdmin "God Mode" tables.
//
// admin_audit_log: an append-only trail of every privileged action a
// super-admin performs (ban, impersonate, role change, …). Denormalized
// actorEmail/targetLabel snapshots keep the log readable even after the
// referenced user/org is deleted. NOT a Better Auth plugin table — these are
// app-owned, so ids are app-generated (crypto.randomUUID) like our other
// domain tables.
import { relations } from "drizzle-orm";
import {
  index,
  integer,
  jsonb,
  pgTable,
  primaryKey,
  text,
  timestamp,
} from "drizzle-orm/pg-core";
import { organization, user } from "./auth-schema";

export const adminAuditLog = pgTable(
  "admin_audit_log",
  {
    id: text("id")
      .primaryKey()
      .$defaultFn(() => crypto.randomUUID()),
    // The super-admin who performed the action. onDelete:set null (no cascade)
    // so the log survives the actor's deletion — actorEmail keeps the snapshot.
    actorId: text("actor_id").references(() => user.id, {
      onDelete: "set null",
    }),
    actorEmail: text("actor_email").notNull(),
    // Dotted verb, e.g. "user.ban" / "user.impersonate" / "org.transfer_owner".
    action: text("action").notNull(),
    // "user" | "organization" | "subscription" | "session" | "system".
    targetType: text("target_type").notNull(),
    targetId: text("target_id"),
    // Human-readable snapshot of the target (email / org name) at action time.
    targetLabel: text("target_label"),
    // Arbitrary structured context, e.g. { reason, oldEmail, newEmail }.
    metadata: jsonb("metadata").$type<Record<string, unknown> | null>(),
    ipAddress: text("ip_address"),
    createdAt: timestamp("created_at").defaultNow().notNull(),
  },
  (table) => [
    index("admin_audit_log_created_at_idx").on(table.createdAt.desc()),
    index("admin_audit_log_actor_idx").on(table.actorId),
    index("admin_audit_log_target_idx").on(table.targetType, table.targetId),
  ],
);

export const adminAuditLogRelations = relations(adminAuditLog, ({ one }) => ({
  actor: one(user, {
    fields: [adminAuditLog.actorId],
    references: [user.id],
  }),
}));

// org_limit_overrides: a super-admin escape hatch to bend an org's plan quotas
// manually (temporary VIP seats, a custom enterprise deal, a goodwill bump)
// BEFORE the matching Stripe price exists. One row per org. Each per-limit
// column is nullable: NULL = "no override for this field, use the plan limit";
// a number wins over the plan value (-1 = unlimited, same convention as plans).
// `expiresAt` (nullable) auto-disables the whole override once past — the
// quota resolver ignores an expired row. NOT a Better Auth plugin table.
export const orgLimitOverrides = pgTable("org_limit_overrides", {
  // PK + FK: exactly one override row per org; gone when the org is deleted.
  organizationId: text("organization_id")
    .primaryKey()
    .references(() => organization.id, { onDelete: "cascade" }),
  // Per-limit overrides — mirror PlanLimits. NULL = inherit the plan value.
  keywords: integer("keywords"),
  projects: integer("projects"),
  seats: integer("seats"),
  integrations: integer("integrations"),
  backlinkRows: integer("backlink_rows"),
  mcpMonthly: integer("mcp_monthly"),
  // Why the override exists (free-text, for the audit trail / UI).
  note: text("note"),
  // NULL = never expires; when set & past, the override is ignored.
  expiresAt: timestamp("expires_at"),
  // The super-admin who last wrote this row (no FK: keep the row if they leave).
  createdBy: text("created_by"),
  createdAt: timestamp("created_at").defaultNow().notNull(),
  updatedAt: timestamp("updated_at").defaultNow().notNull(),
});

export const orgLimitOverridesRelations = relations(
  orgLimitOverrides,
  ({ one }) => ({
    organization: one(organization, {
      fields: [orgLimitOverrides.organizationId],
      references: [organization.id],
    }),
  }),
);

/** RBAC SYS (spec 2026-07-09 §5) — une ligne par permission atomique accordée
 *  à un opérateur Staff SYS (user.role = "staff"). L'Admin SYS (allow-list
 *  env) détient tout implicitement et n'apparaît JAMAIS ici. Le vocabulaire
 *  des permissions vit dans src/lib/auth/sys-permissions.ts. */
export const staffPermission = pgTable(
  "staff_permission",
  {
    userId: text("user_id")
      .notNull()
      .references(() => user.id, { onDelete: "cascade" }),
    permission: text("permission").notNull(),
    grantedBy: text("granted_by").references(() => user.id, {
      onDelete: "set null",
    }),
    grantedAt: timestamp("granted_at", { withTimezone: true })
      .defaultNow()
      .notNull(),
  },
  (t) => [primaryKey({ columns: [t.userId, t.permission] })],
);
