import { resolve } from "node:path";
import { fileURLToPath } from "node:url";

const BLOCK_PAGE_PATTERN = /sorry,? you have been blocked/i;

export function assertPublicResponse({ status, body }) {
  if (status < 200 || status >= 300) {
    throw new Error(`Public access returned HTTP ${status}.`);
  }
  if (BLOCK_PAGE_PATTERN.test(body)) {
    throw new Error("Public access returned a Cloudflare blocked page.");
  }
}

export async function checkPublicAccess(
  url,
  { attempts = 8, fetchImpl = fetch } = {},
) {
  if (!Number.isInteger(attempts) || attempts < 1) {
    throw new Error("Public access attempts must be a positive integer.");
  }

  const baseUrl = new URL(url);
  if (!/^https?:$/.test(baseUrl.protocol)) {
    throw new Error("Public access URL must use HTTP or HTTPS.");
  }

  for (let attempt = 1; attempt <= attempts; attempt += 1) {
    const requestUrl = new URL(baseUrl);
    requestUrl.searchParams.set("hearbooks_access_check", `${Date.now()}-${attempt}`);
    let response;
    try {
      response = await fetchImpl(requestUrl, {
        cache: "no-store",
        redirect: "follow",
        signal: AbortSignal.timeout(15_000),
      });
    } catch (error) {
      throw new Error(`Public access attempt ${attempt} failed.`, { cause: error });
    }
    const body = await response.text();
    assertPublicResponse({ status: response.status, body });
  }

  return { attempts, url: baseUrl.href };
}

const entryPath = process.argv[1] ? resolve(process.argv[1]) : "";
if (entryPath === fileURLToPath(import.meta.url)) {
  const publicUrl = process.argv[2] ?? process.env.HEARBOOKS_URL;
  if (!publicUrl) {
    throw new Error("Pass the public URL or set HEARBOOKS_URL.");
  }
  const result = await checkPublicAccess(publicUrl);
  console.log(`Verified ${result.attempts} clean public responses from ${result.url}`);
}
