/**
 * Lightweight domain config for proxy / hostname classification.
 * Avoids requiring DATABASE_URL during edge-adjacent routing.
 *
 * Hosting environment rules:
 * - Local hostname / localhost → tenant sites at http://{slug}.localhost:{port}
 * - Local LAN IP access (e.g. 192.168.x.x) → http://{ip}:{port}/studio/{slug}
 *   (browsers cannot resolve subdomains of raw IPs)
 * - Online → https://{slug}.{PLATFORM_ROOT_DOMAIN}
 *
 * Canonical subdomain records in DB stay `{slug}.{PLATFORM_ROOT_DOMAIN}` so
 * the same tenant resolves in every environment.
 */

export const RESERVED_SUBDOMAINS = [
  "www",
  "api",
  "admin",
  "app",
  "dashboard",
  "mail",
  "support",
  "status",
  "docs",
  "cdn",
  "assets",
  "static",
  "billing",
  "auth",
  "login",
  "signup",
  "register",
  "help",
  "blog",
  "journal",
  "discover",
  "marketplace",
  "platform",
  "owner",
  "root",
  "system",
  "internal",
  "test",
  "staging",
  "dev",
  "demo",
  "studio",
  "about",
  "team",
  "awards",
  "publications",
  "experience",
  "contact",
  "services",
  "projects",
] as const;

export type ReservedSubdomain = (typeof RESERVED_SUBDOMAINS)[number];

function read(name: string, fallback: string): string {
  return (process.env[name] ?? fallback).trim().toLowerCase();
}

export function getPlatformRootDomain(): string {
  return read("PLATFORM_ROOT_DOMAIN", "archi.com");
}

export function getPlatformAppHost(): string {
  return read("PLATFORM_APP_HOST", "app.archi.com");
}

export function getPlatformAdminHost(): string {
  return read("PLATFORM_ADMIN_HOST", "admin.archi.com");
}

export function getPlatformApiHost(): string {
  return read("PLATFORM_API_HOST", "api.archi.com");
}

export function getDevPlatformHosts(): string[] {
  return read("DEV_PLATFORM_HOSTS", "localhost:3000,127.0.0.1:3000")
    .split(",")
    .map((host) => host.trim())
    .filter(Boolean);
}

export function isReservedSubdomain(slug: string): boolean {
  return RESERVED_SUBDOMAINS.includes(
    slug.toLowerCase() as ReservedSubdomain,
  );
}

export function normalizeHostname(hostname: string): string {
  return hostname.trim().toLowerCase().replace(/\.$/, "");
}

export function hostnameWithoutPort(hostname: string): string {
  const normalized = normalizeHostname(hostname);
  const [host] = normalized.split(":");
  return host ?? normalized;
}

export function isIpAddress(host: string): boolean {
  if (/^\d{1,3}(?:\.\d{1,3}){3}$/.test(host)) return true;
  if (host.includes(":")) return true;
  return false;
}

/**
 * Public app origin from env. Prefer NEXT_PUBLIC_APP_URL for client bundles.
 */
export function getAppOriginUrl(): URL {
  const raw =
    process.env.NEXT_PUBLIC_APP_URL?.trim() ||
    process.env.APP_URL?.trim() ||
    process.env.AUTH_URL?.trim() ||
    "http://localhost:3000";
  try {
    return new URL(raw);
  } catch {
    return new URL("http://localhost:3000");
  }
}

/**
 * True when this deployment is reached via localhost / loopback / LAN IP.
 * Do NOT use NODE_ENV alone — `next start` is production mode on a laptop.
 */
export function isLocalHostingEnvironment(): boolean {
  const host = getAppOriginUrl().hostname.toLowerCase();
  return (
    host === "localhost" ||
    host === "127.0.0.1" ||
    host.endsWith(".localhost") ||
    isIpAddress(host)
  );
}

/** Canonical platform subdomain stored in DB (environment-independent). */
export function getCanonicalTenantSubdomain(slug: string): string {
  return `${slug.trim().toLowerCase()}.${getPlatformRootDomain()}`;
}

type PublicUrlOptions = {
  /** Incoming Host header, e.g. "192.168.18.2:3000" or "localhost:3000" */
  requestHost?: string | null;
  path?: string;
};

function normalizePublicPath(path = "/"): string {
  if (!path || path === "/") return "/";
  return path.startsWith("/") ? path : `/${path}`;
}

/**
 * When the browser is on a LAN IP, tenant "subdomains" cannot exist.
 * Use same-origin path preview: /studio/{slug}/...
 */
export function shouldUseStudioPathPreview(requestHost?: string | null): boolean {
  if (!requestHost) return false;
  return isIpAddress(hostnameWithoutPort(requestHost));
}

/** Host label shown in UI for the current hosting environment. */
export function getTenantPublicHostLabel(
  slug: string,
  options?: Pick<PublicUrlOptions, "requestHost">,
): string {
  const safe = slug.trim().toLowerCase();

  if (!isLocalHostingEnvironment()) {
    return getCanonicalTenantSubdomain(safe);
  }

  if (shouldUseStudioPathPreview(options?.requestHost)) {
    const host = normalizeHostname(options!.requestHost!);
    return `${host}/studio/${safe}`;
  }

  const origin = getAppOriginUrl();
  if (isIpAddress(origin.hostname)) {
    const host = origin.port
      ? `${origin.hostname}:${origin.port}`
      : origin.hostname;
    return `${host}/studio/${safe}`;
  }

  const port = origin.port;
  return port ? `${safe}.localhost:${port}` : `${safe}.localhost`;
}

/**
 * Clickable public site URL for the current hosting environment.
 * - Online → https://{slug}.{root}
 * - Local + LAN IP request → http://{ip}:{port}/studio/{slug}
 * - Local otherwise → http://{slug}.localhost:{port}
 */
export function buildTenantSubdomainUrl(
  slug: string,
  pathOrOptions: string | PublicUrlOptions = "/",
): string {
  const options: PublicUrlOptions =
    typeof pathOrOptions === "string"
      ? { path: pathOrOptions }
      : pathOrOptions;
  const safePath = normalizePublicPath(options.path);
  const safe = slug.trim().toLowerCase();

  if (!isLocalHostingEnvironment()) {
    return `https://${getCanonicalTenantSubdomain(safe)}${safePath === "/" ? "/" : safePath}`;
  }

  const origin = getAppOriginUrl();
  const previewHost =
    options.requestHost && shouldUseStudioPathPreview(options.requestHost)
      ? normalizeHostname(options.requestHost)
      : isIpAddress(origin.hostname)
        ? normalizeHostname(
            origin.port
              ? `${origin.hostname}:${origin.port}`
              : origin.hostname,
          )
        : null;

  if (previewHost) {
    const suffix = safePath === "/" ? "" : safePath;
    return `${origin.protocol}//${previewHost}/studio/${safe}${suffix}`;
  }

  const port = origin.port ? `:${origin.port}` : "";
  const suffix = safePath === "/" ? "/" : safePath;
  return `${origin.protocol}//${safe}.localhost${port}${suffix}`;
}

export type TenantSiteDescriptor = {
  slug: string;
  /** Absolute URL for this environment */
  url: string;
  /** Host:port or host for display */
  host: string;
  /** Canonical production-style host stored in DNS/DB */
  canonicalHost: string;
  environment: "local" | "online";
};

export function describeTenantSite(
  slug: string,
  options?: Pick<PublicUrlOptions, "requestHost">,
): TenantSiteDescriptor {
  const safe = slug.trim().toLowerCase();
  const local = isLocalHostingEnvironment();
  return {
    slug: safe,
    url: buildTenantSubdomainUrl(safe, { requestHost: options?.requestHost }),
    host: getTenantPublicHostLabel(safe, options),
    canonicalHost: getCanonicalTenantSubdomain(safe),
    environment: local ? "local" : "online",
  };
}
