/**
 * Playwright global setup for dev-system tests.
 *
 * 1. Logs in once per user role and saves browser storage state to disk.
 *    Tests use these cached states via `test.use({ storageState })` to avoid
 *    hitting the auth rate limiter (5 attempts / 15 min / email).
 *
 * 2. Ensures reset-test@planarchy.dev exists for the password-reset E2E tests.
 *    If the user is missing, creates them directly in the DB via argon2id hash
 *    + docker exec psql (no tRPC roundtrip needed in setup).
 */
import { execSync } from "node:child_process";
import { chromium, type FullConfig } from "@playwright/test";
import * as fs from "fs";
import * as path from "path";

const USERS = {
  admin: { email: "admin@planarchy.dev", password: "admin123" },
  manager: { email: "manager@planarchy.dev", password: "manager123" },
  viewer: { email: "viewer@planarchy.dev", password: "viewer123" },
} as const;

const RESET_TEST_USER = {
  email: "reset-test@planarchy.dev",
  password: "Dev123456!",
};

const DB_CONTAINER = "capakraken-postgres-1";
const DB_USER = "capakraken";
const DB_NAME = "capakraken";

function psqlExec(sql: string): string {
  return execSync(
    `docker exec -i ${DB_CONTAINER} psql -U ${DB_USER} -d ${DB_NAME} -t -v ON_ERROR_STOP=1`,
    { input: sql, encoding: "utf8" },
  ).trim();
}

/**
 * Ensure reset-test@planarchy.dev exists in the DB.
 * Creates the user directly via SQL + argon2id hash — no email / tRPC roundtrip.
 */
async function ensureResetTestUser(): Promise<void> {
  const count = psqlExec(`SELECT COUNT(*) FROM users WHERE email='${RESET_TEST_USER.email}';`);
  if (parseInt(count, 10) > 0) {
    console.log(`[global-setup] reset-test user already exists — skipping`);
    return;
  }

  console.log(`[global-setup] Creating reset-test user…`);

  const { hash } = await import("@node-rs/argon2");
  const passwordHash = await hash(RESET_TEST_USER.password);

  // argon2id hashes use base64 chars only — safe inside a SQL single-quoted string
  // Column names are camelCase (Prisma default) — must be double-quoted in SQL
  const sql = `
    INSERT INTO users (id, email, name, "systemRole", "passwordHash", "createdAt", "updatedAt")
    VALUES (
      gen_random_uuid()::text,
      '${RESET_TEST_USER.email}',
      'reset-test',
      'USER',
      '${passwordHash}',
      NOW(),
      NOW()
    ) ON CONFLICT (email) DO NOTHING;
  `;

  psqlExec(sql);
  console.log(`[global-setup] Created reset-test user (${RESET_TEST_USER.email})`);
}

async function globalSetup(config: FullConfig) {
  const baseURL = config.projects[0]?.use?.baseURL ?? "http://localhost:3100";
  const authDir = path.join(__dirname, ".auth");
  fs.mkdirSync(authDir, { recursive: true });

  const browser = await chromium.launch();

  for (const [role, creds] of Object.entries(USERS)) {
    const context = await browser.newContext();
    const page = await context.newPage();

    await page.goto(`${baseURL}/auth/signin`);
    await page.fill('input[type="email"]', creds.email);
    await page.fill('input[type="password"]', creds.password);
    await page.click('button[type="submit"]');

    await page.waitForURL(/\/(dashboard|resources)/, { timeout: 15000 });

    await context.storageState({ path: path.join(authDir, `${role}.json`) });
    await context.close();
    console.log(`[global-setup] Saved auth state for ${role}`);
  }

  await browser.close();

  // Ensure the dedicated password-reset test user exists
  await ensureResetTestUser();
}

export default globalSetup;
