import { chromium } from "@playwright/test";
import * as path from "path";
import * as fs from "fs";
import * as dotenv from "dotenv";
import { loginToElement } from "./fixtures/element-auth";

dotenv.config({ path: path.resolve(__dirname, ".env") });

const USER_DATA_DIR = path.resolve(__dirname, ".auth", "chrome-profile");
const MARKER_PATH = path.resolve(__dirname, ".auth", "login-done.marker");
const SCREENSHOTS_DIR = path.resolve(__dirname, "test-results", "global-setup");

/**
 * Global setup: ejecuta login una vez usando persistent context.
 *
 * A diferencia de storageState, el persistent context preserva IndexedDB
 * (crypto keys de E2EE). Los tests usan el mismo userDataDir via el
 * custom fixture persistent-context.ts.
 *
 * Si el marker file existe y no esta expirado, asumimos que la sesion
 * sigue activa y saltamos el login.
 */
async function globalSetup() {
  const elementURL = process.env.ELEMENT_URL || "http://localhost:8080";
  const user = process.env.MATRIX_USER;
  const password = process.env.MATRIX_PASSWORD;
  const recoveryKey = process.env.MATRIX_RECOVERY_KEY;

  if (!user || !password || !recoveryKey) {
    throw new Error(
      "Faltan variables de entorno: MATRIX_USER, MATRIX_PASSWORD, MATRIX_RECOVERY_KEY"
    );
  }

  // Reutilizar sesion cacheada si el marker existe y tiene menos de 12 horas
  if (isMarkerFresh(MARKER_PATH, 12 * 60 * 60 * 1000)) {
    console.log("[global-setup] Reutilizando sesion de persistent context");
    return;
  }

  console.log("[global-setup] Ejecutando login en Element Web con persistent context...");
  console.log(`[global-setup] URL: ${elementURL}`);
  console.log(`[global-setup] User: ${user}`);
  console.log(`[global-setup] UserDataDir: ${USER_DATA_DIR}`);

  // Limpiar perfil anterior para login fresco
  if (fs.existsSync(USER_DATA_DIR)) {
    fs.rmSync(USER_DATA_DIR, { recursive: true });
    console.log("[global-setup] Perfil anterior eliminado");
  }

  // Asegurar que los directorios existen
  fs.mkdirSync(USER_DATA_DIR, { recursive: true });
  fs.mkdirSync(SCREENSHOTS_DIR, { recursive: true });

  // Usar persistent context — preserva IndexedDB (crypto keys E2EE)
  const context = await chromium.launchPersistentContext(USER_DATA_DIR, {
    headless: true,
    viewport: { width: 1280, height: 720 },
  });

  const page = context.pages()[0] || (await context.newPage());

  // Capturar logs de consola del browser
  page.on("console", (msg) => {
    const type = msg.type();
    if (type === "error" || type === "warning") {
      console.log(`[browser-${type}] ${msg.text()}`);
    }
  });
  page.on("pageerror", (err) => {
    console.error(`[browser-error] ${err.message}`);
  });

  try {
    await loginToElement(page, {
      url: elementURL,
      user,
      password,
      recoveryKey,
      screenshotsDir: SCREENSHOTS_DIR,
    });

    // Crear marker de sesion exitosa
    fs.writeFileSync(MARKER_PATH, new Date().toISOString());
    console.log("[global-setup] Login completado, marker creado");

    await page.screenshot({
      path: path.join(SCREENSHOTS_DIR, "05-login-complete.png"),
      fullPage: true,
    });
  } catch (err) {
    console.error("[global-setup] ERROR durante login:", err);
    await page.screenshot({
      path: path.join(SCREENSHOTS_DIR, "ERROR-login-failed.png"),
      fullPage: true,
    });
    const html = await page.content();
    fs.writeFileSync(
      path.join(SCREENSHOTS_DIR, "ERROR-page-content.html"),
      html
    );
    throw err;
  } finally {
    await context.close();
  }
}

/** Verifica si el marker file existe y tiene menos de maxAge ms. */
function isMarkerFresh(filePath: string, maxAge: number): boolean {
  try {
    const stat = fs.statSync(filePath);
    return Date.now() - stat.mtimeMs < maxAge;
  } catch {
    return false;
  }
}

export default globalSetup;
