import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

import {
  normalizeSupportedLocale,
} from "./src/lib/i18n-config";
import {
  parseLocalizedPublicPath,
} from "./src/lib/i18n-urls";
import { hasLocalizedBlogArticle } from "./src/lib/localized-blog-slugs";

const MAIL_HOST = "mail.officialsite.kr";
const PUBLIC_HOST = "officialsite.kr";
const WWW_PUBLIC_HOST = "www.officialsite.kr";
const PUBLIC_SITE_ORIGIN = "https://officialsite.kr";
const MAIL_APP_ORIGIN = "https://mail.officialsite.kr";
const PUBLIC_SITE_PATHS = [
  "/business-email",
  "/domain-email",
  "/domain-mail-check",
  "/ai-email-summary",
  "/team-mailbox",
  "/secure-business-email",
  "/faq",
  "/blog",
  "/guide",
  "/partner",
  "/terms",
  "/privacy",
  "/account-deletion",
  "/feed.xml",
  "/llms.txt",
  "/llms-full.txt",
];
const MAIL_APP_PATHS = [
  "/api",
  "/dashboard",
  "/find-id",
  "/kavenix",
  "/login",
  "/mail",
  "/mail-setup",
  "/payments",
  "/reset-password",
  "/signup",
];
const PUBLIC_API_PATHS = [
  "/api/blog",
  "/api/partner-inquiries",
  "/api/tools/domain-mail-check",
];
const MAIL_HOST_ROBOTS = [
  "User-agent: *",
  "Disallow: /",
  "",
  `Sitemap: ${PUBLIC_SITE_ORIGIN}/sitemap.xml`,
  "",
].join("\n");

function isPathMatch(pathname: string, paths: string[]) {
  return paths.some(
    (path) => pathname === path || pathname.startsWith(`${path}/`),
  );
}

function isPublicSitePath(pathname: string) {
  return isPathMatch(pathname, PUBLIC_SITE_PATHS);
}

function isPublicPagePath(pathname: string) {
  return pathname === "/" || isPublicSitePath(pathname);
}

function supportsLocalizedPublicPage(pathname: string) {
  const match = /^\/blog\/([^/]+)\/?$/.exec(pathname);

  if (!match) {
    return true;
  }

  try {
    return hasLocalizedBlogArticle(decodeURIComponent(match[1]));
  } catch {
    return false;
  }
}

function isMailAppPath(pathname: string) {
  return isPathMatch(pathname, MAIL_APP_PATHS);
}

function isPublicApiPath(pathname: string) {
  return isPathMatch(pathname, PUBLIC_API_PATHS);
}

function redirectToOrigin(nextUrl: NextRequest["nextUrl"], origin: string) {
  const url = new URL(nextUrl.pathname, origin);
  url.search = nextUrl.search;
  return NextResponse.redirect(url, 308);
}

function rewriteLocalizedPublicPage(
  request: NextRequest,
  locale: NonNullable<ReturnType<typeof normalizeSupportedLocale>>,
  pathname: string,
) {
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set("x-official-locale", locale);
  requestHeaders.set("x-official-public-path", pathname);

  if (request.nextUrl.pathname === pathname) {
    return NextResponse.next({
      request: { headers: requestHeaders },
    });
  }

  const rewriteUrl = request.nextUrl.clone();
  rewriteUrl.pathname = pathname;

  // The blue/green upstream listens on plain HTTP even when Apache forwards
  // the original public request as HTTPS metadata.
  if (
    rewriteUrl.hostname === "localhost" ||
    rewriteUrl.hostname === "127.0.0.1"
  ) {
    rewriteUrl.protocol = "http:";
  }

  return NextResponse.rewrite(rewriteUrl, {
    request: { headers: requestHeaders },
  });
}

function publicRedirectUrl(request: NextRequest, pathname: string) {
  const host = request.headers.get("host")?.split(":")[0]?.toLowerCase() ?? "";
  const url =
    host === PUBLIC_HOST || host === WWW_PUBLIC_HOST
      ? new URL(pathname, PUBLIC_SITE_ORIGIN)
      : request.nextUrl.clone();

  url.pathname = pathname;
  url.search = request.nextUrl.search;
  return url;
}

export function proxy(request: NextRequest) {
  const { nextUrl, headers } = request;
  const host = headers.get("host")?.split(":")[0]?.toLowerCase() ?? "";
  const isLocalHost = host === "localhost" || host === "127.0.0.1";
  const localizedPath = parseLocalizedPublicPath(nextUrl.pathname);
  const forwardedProtocol =
    headers.get("x-forwarded-proto")?.split(",")[0]?.trim().toLowerCase() ??
    nextUrl.protocol.replace(":", "").toLowerCase();

  if (
    forwardedProtocol === "http" &&
    !isLocalHost &&
    (host === PUBLIC_HOST || host === WWW_PUBLIC_HOST || host === MAIL_HOST)
  ) {
    const origin =
      host === MAIL_HOST ||
      (isMailAppPath(nextUrl.pathname) && !isPublicApiPath(nextUrl.pathname))
        ? MAIL_APP_ORIGIN
        : PUBLIC_SITE_ORIGIN;
    return redirectToOrigin(nextUrl, origin);
  }

  // Beacons must stay same-origin on both the public site and the mail app.
  // A cross-origin redirect makes application/json tracking fail CORS checks.
  if (nextUrl.pathname === "/api/marketing/track") {
    return NextResponse.next();
  }

  if (localizedPath && !isPublicPagePath(localizedPath.pathname)) {
    return NextResponse.next();
  }

  if (localizedPath && host === MAIL_HOST) {
    return redirectToOrigin(nextUrl, PUBLIC_SITE_ORIGIN);
  }

  if (
    localizedPath &&
    (host === PUBLIC_HOST || host === WWW_PUBLIC_HOST || isLocalHost)
  ) {
    if (host === WWW_PUBLIC_HOST) {
      return redirectToOrigin(nextUrl, PUBLIC_SITE_ORIGIN);
    }

    if (!supportsLocalizedPublicPage(localizedPath.pathname)) {
      return NextResponse.redirect(
        publicRedirectUrl(request, localizedPath.pathname),
        308,
      );
    }

    return rewriteLocalizedPublicPage(
      request,
      localizedPath.locale,
      localizedPath.pathname,
    );
  }

  if (host === WWW_PUBLIC_HOST) {
    return redirectToOrigin(
      nextUrl,
      isMailAppPath(nextUrl.pathname) && !isPublicApiPath(nextUrl.pathname)
        ? MAIL_APP_ORIGIN
        : PUBLIC_SITE_ORIGIN,
    );
  }

  if ((host === PUBLIC_HOST || isLocalHost) && isPublicPagePath(nextUrl.pathname)) {
    if (!supportsLocalizedPublicPage(nextUrl.pathname)) {
      return rewriteLocalizedPublicPage(request, "ko", nextUrl.pathname);
    }

    const routedLocale = normalizeSupportedLocale(
      headers.get("x-official-locale"),
    );
    const routedPath = headers.get("x-official-public-path");
    if (routedLocale && routedPath === nextUrl.pathname) {
      return NextResponse.next();
    }

    // Public URLs without a locale prefix are always the canonical Korean
    // version. Localized content is available only through explicit paths.
    return rewriteLocalizedPublicPage(request, "ko", nextUrl.pathname);
  }

  if (
    host === PUBLIC_HOST &&
    isMailAppPath(nextUrl.pathname) &&
    !isPublicApiPath(nextUrl.pathname)
  ) {
    return redirectToOrigin(nextUrl, MAIL_APP_ORIGIN);
  }

  if (host === MAIL_HOST && nextUrl.pathname === "/robots.txt") {
    return new NextResponse(MAIL_HOST_ROBOTS, {
      headers: {
        "content-type": "text/plain; charset=utf-8",
      },
    });
  }

  if (host === MAIL_HOST && nextUrl.pathname === "/sitemap.xml") {
    return redirectToOrigin(nextUrl, PUBLIC_SITE_ORIGIN);
  }

  if (
    host === MAIL_HOST &&
    (
      nextUrl.pathname === "/" ||
      isPublicSitePath(nextUrl.pathname) ||
      isPublicApiPath(nextUrl.pathname)
    )
  ) {
    return redirectToOrigin(nextUrl, PUBLIC_SITE_ORIGIN);
  }

  if (host === MAIL_HOST) {
    const response = NextResponse.next();
    response.headers.set("X-Robots-Tag", "noindex, nofollow, noarchive");
    return response;
  }

  return NextResponse.next();
}

export const config = {
  matcher: "/:path*",
};
