/**
 * Exercises the REAL GDPR data-export and account-deletion paths against the
 * live (dev) DB to prove the system works end-to-end: seeds a throwaway user
 * with portfolio data + a stored file, exports, then runs the deletion drain
 * and asserts everything is gone (and the compliance evidence remains).
 * Run: npx tsx scripts/verify-gdpr.ts
 */
import { config } from "dotenv"
config({ path: ".env.local" })
process.env.DATABASE_SSL = process.env.DATABASE_SSL ?? "disable"

const TEST_USER_ID = "gdpr-verify-user"
const TEST_EMAIL = "gdpr-verify@example.com"

let failures = 0
function check(label: string, ok: boolean, detail?: string) {
  console.log(`  ${ok ? "✓" : "✗"} ${label}${!ok && detail ? ` — ${detail}` : ""}`)
  if (!ok) failures++
}

async function main() {
  const { db, pool } = await import("../lib/db")
  const s = await import("../lib/db/schema")
  const { eq, and } = await import("drizzle-orm")
  const storage = await import("../lib/storage")
  const { buildUserDataExport } = await import("../lib/gdpr/export")
  const { processDueDeletions } = await import("../lib/gdpr/delete")

  // ── cleanup any prior run ──────────────────────────────────────────────────
  await db.delete(s.user).where(eq(s.user.id, TEST_USER_ID))
  await db.delete(s.consent_log).where(eq(s.consent_log.user_id, TEST_USER_ID))
  await db.delete(s.account_deletion_requests).where(eq(s.account_deletion_requests.user_id, TEST_USER_ID))
  await db.delete(s.admin_audit_log).where(eq(s.admin_audit_log.target_user_id, TEST_USER_ID))

  // ── seed ───────────────────────────────────────────────────────────────────
  console.log("── Seeding throwaway user + portfolio ───")
  await db.insert(s.user).values({ id: TEST_USER_ID, name: "GDPR Verify", email: TEST_EMAIL })
  await db.insert(s.profiles).values({ id: TEST_USER_ID, email: TEST_EMAIL, full_name: "GDPR Verify" })
  const [prop] = await db
    .insert(s.properties)
    .values({ user_id: TEST_USER_ID, name: "Test House", address_line1: "1 Test St", city: "Testville" })
    .returning()
  const [tenant] = await db
    .insert(s.tenants)
    .values({ user_id: TEST_USER_ID, property_id: prop.id, first_name: "Tina", last_name: "Tenant", email: "tina@example.com" })
    .returning()
  await db.insert(s.rent_payments).values({
    user_id: TEST_USER_ID, tenant_id: tenant.id, property_id: prop.id, amount: 1200, due_date: "2026-07-01",
  })
  await db.insert(s.api_keys).values({
    user_id: TEST_USER_ID, name: "test key", key_hash: `hash-${Date.now()}`, key_prefix: "pmn_test",
  })
  await db.insert(s.consent_log).values([
    { user_id: TEST_USER_ID, email: TEST_EMAIL, kind: "terms", granted: true, source: "signup" },
    { user_id: TEST_USER_ID, email: TEST_EMAIL, kind: "privacy", granted: true, source: "signup" },
  ])
  const { key: fileKey } = await storage.saveBuffer(Buffer.from("gdpr verify payload"), {
    userId: TEST_USER_ID, scope: "verify", ext: "txt",
  })
  console.log(`  seeded property=${prop.id.slice(0, 8)} tenant=${tenant.id.slice(0, 8)} file=${fileKey}`)

  // ── export ─────────────────────────────────────────────────────────────────
  console.log("── Data export (Articles 15/20) ─────────")
  const exp = await buildUserDataExport(TEST_USER_ID)
  check("subject user present", exp.data_subject.user?.email === TEST_EMAIL)
  check("profile present", exp.data_subject.profile?.id === TEST_USER_ID)
  check("property exported", exp.portfolio.properties.length === 1)
  check("tenant exported", exp.portfolio.tenants.length === 1)
  check("payment exported", exp.portfolio.rent_payments.length === 1)
  check("consent history exported", exp.privacy.consent_log.length === 2)
  check("api key exported WITHOUT hash",
    exp.automation.api_keys.length === 1 && !("key_hash" in exp.automation.api_keys[0]))
  const serialized = JSON.stringify(exp)
  check("no key_hash anywhere in export", !serialized.includes("key_hash"))
  check("no password field anywhere in export", !serialized.includes('"password"'))

  // ── deletion drain ─────────────────────────────────────────────────────────
  console.log("── Deletion (Article 17) ────────────────")
  await db.insert(s.account_deletion_requests).values({
    user_id: TEST_USER_ID,
    email: null, // null → no completion email attempt from the drain
    scheduled_for: new Date(Date.now() - 60_000).toISOString(), // due 1 min ago
  })
  const { processed, deleted } = await processDueDeletions(50)
  check("drain picked up the request", processed >= 1)
  check("drain deleted the account", deleted >= 1)

  const userAfter = await db.query.user.findFirst({ where: eq(s.user.id, TEST_USER_ID) })
  check("user row deleted", !userAfter)
  const profileAfter = await db.query.profiles.findFirst({ where: eq(s.profiles.id, TEST_USER_ID) })
  check("profile cascaded", !profileAfter)
  const propsAfter = await db.query.properties.findMany({ where: eq(s.properties.user_id, TEST_USER_ID) })
  check("properties cascaded", propsAfter.length === 0)
  const tenantsAfter = await db.query.tenants.findMany({ where: eq(s.tenants.user_id, TEST_USER_ID) })
  check("tenants cascaded", tenantsAfter.length === 0)
  const keysAfter = await db.query.api_keys.findMany({ where: eq(s.api_keys.user_id, TEST_USER_ID) })
  check("api keys cascaded", keysAfter.length === 0)

  const request = await db.query.account_deletion_requests.findFirst({
    where: eq(s.account_deletion_requests.user_id, TEST_USER_ID),
  })
  check("request marked completed", request?.status === "completed")
  check("request email nulled", request?.email === null)

  const consents = await db.query.consent_log.findMany({ where: eq(s.consent_log.user_id, TEST_USER_ID) })
  check("consent facts retained", consents.length === 2)
  check("consent PII anonymized", consents.every((c) => c.email === null && c.ip_address === null))

  const audit = await db.query.admin_audit_log.findFirst({
    where: and(eq(s.admin_audit_log.target_user_id, TEST_USER_ID), eq(s.admin_audit_log.action, "gdpr_delete_account")),
  })
  check("audit evidence written (system action, admin_id null)", !!audit && audit.admin_id === null)

  const bytesAfter = await storage.getUserStorageBytes(TEST_USER_ID)
  check("stored files purged", bytesAfter === 0, `${bytesAfter} bytes remain`)

  // ── cleanup compliance rows from the test run ──────────────────────────────
  await db.delete(s.consent_log).where(eq(s.consent_log.user_id, TEST_USER_ID))
  await db.delete(s.account_deletion_requests).where(eq(s.account_deletion_requests.user_id, TEST_USER_ID))
  await db.delete(s.admin_audit_log).where(eq(s.admin_audit_log.target_user_id, TEST_USER_ID))

  console.log(failures === 0 ? "\nALL CHECKS PASSED ✓" : `\n${failures} CHECK(S) FAILED ✗`)
  await pool.end()
  process.exit(failures === 0 ? 0 : 1)
}

main().catch((e) => {
  console.error(e)
  process.exit(1)
})
