import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { isReservedSubdomain } from "@/core/config/domains";
import { classifyHostname } from "@/core/tenant/classify-hostname";

/**
 * Next.js 16 Proxy (formerly middleware).
 * Classifies host and rewrites into platform / app / admin / tenant route trees.
 *
 * Tenant identity is NOT fully resolved here for every request when DB is needed
 * for custom domains — lightweight classification + header propagation.
 * Full TenantContext is established in server layouts/services.
 *
 * CRITICAL: Never rewrite unknown tenants to a default tenant.
 *
 * LAN note: browsers cannot resolve `{slug}.{ip}`. On platform/IP hosts we
 * support path preview `/studio/{slug}/...` → tenant site rewrite.
 */
export function proxy(request: NextRequest) {
  const hostname = request.headers.get("host") ?? "localhost:3000";
  const { pathname } = request.nextUrl;

  // Health checks pass through
  if (pathname === "/health" || pathname === "/ready") {
    return NextResponse.next();
  }

  // Auth lives on the landing modal — no standalone /login page.
  if (pathname === "/login") {
    const url = request.nextUrl.clone();
    url.pathname = "/";
    url.search = "";
    url.searchParams.set("auth", "login");
    return NextResponse.redirect(url);
  }

  const hostKind = classifyHostname(hostname);
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set("x-archi-hostname", hostname);
  requestHeaders.set("x-archi-host-kind", hostKind.kind);

  // API routes must never be rewritten into /site — but they still need tenant
  // identity headers (inquiries, public APIs) when called from a studio host.
  if (pathname.startsWith("/api")) {
    if (hostKind.kind === "tenant_subdomain") {
      requestHeaders.set("x-archi-tenant-slug", hostKind.slug);
      requestHeaders.set("x-archi-host-kind", "tenant_subdomain");
    } else if (hostKind.kind === "custom_domain") {
      requestHeaders.set("x-archi-custom-domain", hostKind.domain);
      requestHeaders.set("x-archi-host-kind", "custom_domain");
    } else {
      // LAN / platform: allow client or Referer studio slug (e.g. /studio/mukhsin)
      const fromHeader = request.headers
        .get("x-archi-tenant-slug")
        ?.trim()
        .toLowerCase();
      const fromReferer = studioSlugFromReferer(
        request.headers.get("referer"),
      );
      const slug = fromHeader || fromReferer;
      if (slug && !isReservedSubdomain(slug) && /^[a-z0-9-]+$/.test(slug)) {
        requestHeaders.set("x-archi-tenant-slug", slug);
      }
    }
    return NextResponse.next({ request: { headers: requestHeaders } });
  }

  // Path-based studio preview on platform/LAN hosts:
  // /studio/mukhsin → /site  (with x-archi-tenant-slug)
  const studioPreview = matchStudioPreviewPath(pathname);
  if (
    studioPreview &&
    (hostKind.kind === "platform" || hostKind.kind === "unknown")
  ) {
    requestHeaders.set("x-archi-tenant-slug", studioPreview.slug);
    requestHeaders.set("x-archi-host-kind", "tenant_subdomain");
    requestHeaders.set(
      "x-archi-studio-base",
      `/studio/${studioPreview.slug}`,
    );
    const url = request.nextUrl.clone();
    url.pathname = mapTenantPath(studioPreview.restPath);
    return NextResponse.rewrite(url, {
      request: { headers: requestHeaders },
    });
  }

  if (hostKind.kind === "tenant_subdomain") {
    requestHeaders.set("x-archi-tenant-slug", hostKind.slug);
    const url = request.nextUrl.clone();
    url.pathname = mapTenantPath(pathname);
    return NextResponse.rewrite(url, {
      request: { headers: requestHeaders },
    });
  }

  if (hostKind.kind === "custom_domain") {
    requestHeaders.set("x-archi-custom-domain", hostKind.domain);
    const url = request.nextUrl.clone();
    url.pathname = mapTenantPath(pathname);
    return NextResponse.rewrite(url, {
      request: { headers: requestHeaders },
    });
  }

  if (hostKind.kind === "app") {
    const url = request.nextUrl.clone();
    if (!pathname.startsWith("/dashboard")) {
      url.pathname = pathname === "/" ? "/dashboard" : `/dashboard${pathname}`;
      return NextResponse.rewrite(url, {
        request: { headers: requestHeaders },
      });
    }
    return NextResponse.next({ request: { headers: requestHeaders } });
  }

  if (hostKind.kind === "admin") {
    const url = request.nextUrl.clone();
    if (!pathname.startsWith("/admin")) {
      url.pathname = pathname === "/" ? "/admin" : `/admin${pathname}`;
      return NextResponse.rewrite(url, {
        request: { headers: requestHeaders },
      });
    }
    return NextResponse.next({ request: { headers: requestHeaders } });
  }

  // Platform / api / unknown → continue (unknown tenant pages handle 404)
  return NextResponse.next({ request: { headers: requestHeaders } });
}

function matchStudioPreviewPath(
  pathname: string,
): { slug: string; restPath: string } | null {
  const match = pathname.match(/^\/studio\/([^/]+)(\/.*)?$/);
  if (!match) return null;
  const slug = (match[1] ?? "").toLowerCase();
  if (!slug || isReservedSubdomain(slug) || slug.includes(".")) {
    return null;
  }
  return {
    slug,
    restPath: match[2] && match[2].length > 0 ? match[2] : "/",
  };
}

function studioSlugFromReferer(referer: string | null): string | null {
  if (!referer) return null;
  try {
    const path = new URL(referer).pathname;
    return matchStudioPreviewPath(path)?.slug ?? null;
  } catch {
    return null;
  }
}

function mapTenantPath(pathname: string): string {
  if (pathname.startsWith("/site") || pathname.startsWith("/api")) {
    return pathname;
  }
  if (pathname === "/") {
    return "/site";
  }
  return `/site${pathname}`;
}

export const config = {
  matcher: [
    "/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico)$).*)",
  ],
};
