/**
 * Single source of truth for the public site origin.
 *
 * Set `NEXT_PUBLIC_APP_URL` to the production domain before launch — canonical
 * tags, Open Graph URLs, the sitemap and robots.txt all derive from it. Falling
 * back to localhost keeps local development working, but shipping with that
 * fallback active would emit localhost URLs into the sitemap.
 */
const rawSiteUrl = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000";

/** Origin without a trailing slash, safe to concatenate paths onto. */
export const siteUrl = rawSiteUrl.replace(/\/+$/, "");

/** True once a real domain is configured — useful for guarding indexability. */
export const isProductionSite =
  !siteUrl.includes("localhost") && !siteUrl.includes("127.0.0.1");

/** Hostname/domain of the site without protocol or port, with fallback to scanreceipts.app. */
export function getSiteDomain(): string {
  try {
    const url = new URL(siteUrl);
    if (url.hostname === "localhost" || url.hostname === "127.0.0.1") {
      return "scanreceipts.app";
    }
    return url.hostname;
  } catch {
    return "scanreceipts.app";
  }
}

export const siteDomain = getSiteDomain();

/** Host (incl. port) portion of a URL, best-effort. */
export function hostnameOf(url: string): string {
  try {
    return new URL(url).host;
  } catch {
    return url;
  }
}

/**
 * Host labels the middleware routes back into this app
 * (src/middleware.ts): `app.*` → dashboard, `admin.*` → admin. Keeping the
 * list in one place lets the CSRF origin check and the Google OAuth return
 * logic validate against exactly the hosts the app actually serves.
 */
export const FIRST_PARTY_SUBDOMAIN_LABELS = ["app", "admin"] as const;

/**
 * True when `host` is `base` itself or one of the routed first-party
 * subdomains (`app.<base>`, `admin.<base>`). Case-insensitive.
 */
export function hostIsFirstParty(host: string, baseHost: string): boolean {
  const norm = host.toLowerCase();
  const base = baseHost.toLowerCase();
  if (norm === base) return true;
  return FIRST_PARTY_SUBDOMAIN_LABELS.some((label) => norm === `${label}.${base}`);
}

/** `hostIsFirstParty` against the site's own host (from `siteUrl`). */
export function hostIsSiteFirstParty(host: string): boolean {
  return hostIsFirstParty(host, hostnameOf(siteUrl));
}

/**
 * Origin to use for a response that should land back in the room the user
 * started from: the site's scheme (from `siteUrl`) + the request host. This
 * keeps Stripe success/cancel URLs and post-login destinations on the exact
 * `app.*`/`admin.*` origin instead of bouncing to the bare domain. Any
 * non-first-party host falls back to the bare `siteUrl`, so the host value can
 * never become an attacker-controlled redirect target.
 */
export function originForFirstPartyHost(host: string): string {
  if (!hostIsSiteFirstParty(host)) return siteUrl;
  const url = new URL(siteUrl);
  url.host = host;
  return url.origin;
}
