#!/usr/bin/env node

const BASE_URL = [
  process.env.OPS_BASE_URL,
  process.env.APP_URL,
  process.env.NEXT_PUBLIC_APP_URL
].map((value) => value?.trim()).find(Boolean);

const TEST_EMAIL = process.env.OPS_SESSION_CHECK_EMAIL?.trim();
const TEST_PASSWORD = process.env.OPS_SESSION_CHECK_PASSWORD?.trim();
const EXPECTED_TTL_SECONDS = resolveSessionTtl(process.env.SESSION_TTL_SECONDS);
const SESSION_COOKIE_NAME = "wa_inbox_session";

if (!BASE_URL) {
  console.error("[ops-session-check] Missing OPS_BASE_URL / APP_URL / NEXT_PUBLIC_APP_URL");
  process.exit(1);
}

if (!TEST_EMAIL || !TEST_PASSWORD) {
  console.error("[ops-session-check] Missing OPS_SESSION_CHECK_EMAIL / OPS_SESSION_CHECK_PASSWORD. Test skipped.");
  process.exit(1);
}

function resolveSessionTtl(value) {
  if (!value) {
    return 60 * 60 * 24 * 7;
  }
  const parsed = Number(value.trim());
  if (!Number.isFinite(parsed) || parsed <= 0) {
    return 60 * 60 * 24 * 7;
  }
  return Math.floor(parsed);
}

function readCookieLines(headers) {
  const direct = [];
  if (typeof headers.getSetCookie === "function") {
    const lines = headers.getSetCookie();
    if (Array.isArray(lines)) {
      return lines;
    }
  }

  headers.forEach((value, key) => {
    if (key.toLowerCase() === "set-cookie") {
      direct.push(value);
    }
  });

  return direct;
}

function getCookieValue(cookieHeader, name) {
  const prefix = `${name}=`;
  const found = cookieHeader.find((entry) => entry.startsWith(prefix));
  if (!found) {
    return null;
  }

  const [value] = found.split(";")[0].split("=", 2).slice(1);
  if (typeof value !== "string") {
    return null;
  }
  return `${found.split(";")[0].slice(prefix.length)}`;
}

function getCookieTtlSeconds(cookieHeader, name) {
  const prefix = `${name}=`;
  const found = cookieHeader.find((entry) => entry.startsWith(prefix));
  if (!found) {
    return null;
  }

  const parts = found.split(";").map((part) => part.trim());
  const attrs = new Map();
  for (const part of parts.slice(1)) {
    const [rawKey, rawValue] = part.split("=");
    attrs.set(rawKey.toLowerCase(), rawValue ?? "");
  }

  const maxAgeRaw = attrs.get("max-age");
  if (maxAgeRaw) {
    const parsed = Number(maxAgeRaw);
    if (Number.isFinite(parsed)) {
      return Math.floor(parsed);
    }
  }

  const expiresRaw = attrs.get("expires");
  if (expiresRaw) {
    const parsedDate = new Date(expiresRaw);
    if (!Number.isNaN(parsedDate.getTime())) {
      return Math.floor((parsedDate.getTime() - Date.now()) / 1000);
    }
  }

  return null;
}

async function requestJson(url, options = {}) {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), 12_000);

  try {
    const response = await fetch(url, {
      ...options,
      signal: controller.signal
    });
    clearTimeout(timeout);
    return response;
  } catch (error) {
    clearTimeout(timeout);
    throw error;
  }
}

async function main() {
  const loginHeaders = {
    "Content-Type": "application/x-www-form-urlencoded",
    "User-Agent": "ops-session-check"
  };
  const loginBody = new URLSearchParams({
    email: TEST_EMAIL,
    password: TEST_PASSWORD,
    next: "/super-admin"
  }).toString();

  const loginResponse = await requestJson(`${BASE_URL}/auth/login`, {
    method: "POST",
    redirect: "manual",
    headers: loginHeaders,
    body: loginBody
  });

  if (loginResponse.status !== 307 && loginResponse.status !== 302) {
    console.error(`[ops-session-check] login status unexpected: ${loginResponse.status}`);
    process.exit(1);
  }

  const setCookieLines = readCookieLines(loginResponse.headers);
  const sessionCookieValue = getCookieValue(setCookieLines, SESSION_COOKIE_NAME);
  if (!sessionCookieValue) {
    console.error("[ops-session-check] session cookie not issued by /auth/login");
    process.exit(1);
  }

  const ttl = getCookieTtlSeconds(setCookieLines, SESSION_COOKIE_NAME);
  if (ttl === null) {
    console.error("[ops-session-check] session cookie ttl missing");
    process.exit(1);
  }

  if (Math.abs(ttl - EXPECTED_TTL_SECONDS) > 600) {
    console.warn(
      `[ops-session-check] session ttl unexpected: ${ttl}s (expected ${EXPECTED_TTL_SECONDS}s ±600s)`
    );
  } else {
    console.log(`[ops-session-check] session ttl check OK: ${ttl}s`);
  }

  const protected = await requestJson(`${BASE_URL}/super-admin`, {
    method: "GET",
    redirect: "manual",
    headers: {
      Cookie: `${SESSION_COOKIE_NAME}=${sessionCookieValue}`
    }
  });

  if (protected.status === 200) {
    console.log("[ops-session-check] protected path access OK (HTTP 200).");
    process.exit(0);
  }

  if (protected.status >= 300 && protected.status < 400) {
    const location = protected.headers.get("location") || "";
    if (location.includes("/login")) {
      console.error("[ops-session-check] protected path redirected to login; session not accepted.");
      process.exit(1);
    }
  }

  console.error(`[ops-session-check] protected path check failed with status ${protected.status}`);
  process.exit(1);
}

main().catch((error) => {
  console.error("[ops-session-check] failed:", error instanceof Error ? error.message : String(error));
  process.exit(1);
});
