import { jsonError } from "../../common.js";

export async function onRequestPost(context: RequestContext) {
  const { destination, path } = context.data.body;

  if (typeof path !== "string" || path.length > 256)
    return jsonError("Invalid path", 400);

  const result = await context.env.D1.prepare(
    "SELECT path FROM short_links WHERE path = ?;",
  )
    .bind(path)
    .first();

  if (result)
    return jsonError(
      "Short link with that path already exists, please choose a different one.",
      400,
    );

  let url: URL;

  try {
    url = new URL(destination);
  } catch {
    return jsonError("Invalid URL", 400);
  }

  if (!["http:", "https:"].includes(url.protocol))
    return jsonError("Invalid URL", 400);

  const dnsCheckPromises = await Promise.allSettled([
    fetch(`https://cloudflare-dns.com/dns-query?name=${url.hostname}&type=a`, {
      headers: {
        accept: "application/dns-json",
      },
    }),
    fetch(
      `https://cloudflare-dns.com/dns-query?name=${url.hostname}&type=aaaa`,
      {
        headers: {
          accept: "application/dns-json",
        },
      },
    ),
  ]);

  const fulfilledResponses = dnsCheckPromises
    .filter((p) => p.status === "fulfilled")
    .map((p) => p.value);

  if (!fulfilledResponses.length)
    return jsonError("Failed to validate hostname", 500);

  let hasAnyValidRecord = false;

  for (const response of fulfilledResponses) {
    if (!response.ok) continue;

    let body: { Status: number; [k: string]: any };

    try {
      body = await response.json();
    } catch {
      continue;
    }

    // A DNS record exists
    if (body.Status === 0) {
      hasAnyValidRecord = true;
      break;
    }
  }

  if (!hasAnyValidRecord)
    return jsonError(
      "This URL appears to not exist, please check and try again.",
      400,
    );

  await context.env.D1.prepare(
    "INSERT INTO short_links (created_at, destination, path, user) VALUES (?, ?, ?, ?);",
  )
    .bind(Date.now(), destination, path, context.data.current_user.id)
    .run();

  return new Response(null, {
    status: 204,
  });
}