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

import { DEFAULT_LOCALE, LOCALE_ALIASES, LOCALES, type Locale } from "./lib/locales";
import { resolveRoute } from "./lib/routes";

/**
 * RRYM / 002 — SULSYS
 * Request proxy (what earlier Next.js versions called middleware).
 *
 * It does three things and nothing else, so route behaviour stays readable:
 *
 *  1. `/` redirects to a locale — the stored `lang` cookie first, then
 *     Accept-Language, then Albanian. No IP geolocation (Blueprint 03).
 *  2. The old Joomla asset and admin directories return 410 Gone, so the
 *     screenshots that exposed personal data are not merely redirected
 *     (Blueprint 13, BLUEPRINT-DELTA D-12).
 *  3. A path inside a locale tree that the route registry does not know is
 *     served that locale's own 404 page, with a 404 status. Next cannot do
 *     this on its own here: the locale segment is the root layout, so an
 *     unmatched path has no layout to render a not-found boundary in, and the
 *     visitor would get the framework's bare English page instead of one in
 *     the language they were reading.
 *  4. Any other path outside the four locale trees is sent to `/sq`.
 *
 * Specific legacy URLs (index.php with its query string, kontakt.html, the
 * module brand-name aliases) are handled by `redirects` in next.config.ts,
 * which Next.js evaluates before this proxy runs.
 */

export const config = {
  matcher: [
    /*
     * Everything except Next's own assets and the files served from the
     * public directory by name.
     *
     * Every directory under public/ has to be listed here. A path that is not
     * excluded falls through to rule 4 at the bottom of this file and is 301'd
     * to the Albanian home page — so a missing entry does not 404 a file, it
     * silently redirects it, and the only symptom is a broken image. That is
     * what happened to the first video poster; `screens/` and `photos/` are
     * both named in public/README.md and both belong here.
     */
    "/((?!_next/|favicon|icon|apple-icon|robots\\.txt|sitemap\\.xml|fonts/|brand/|screens/|photos/|map/).*)",
  ],
};

/** Paths that must be gone, not moved. */
const GONE_PREFIXES = [
  "/images/",
  "/cache/",
  "/media/",
  "/templates/",
  "/components/",
  "/modules/",
  "/plugins/",
  "/administrator",
  "/libraries/",
  "/language/",
];

const LOCALE_COOKIE = "lang";

function isLocale(value: string | undefined): value is Locale {
  return value !== undefined && (LOCALES as readonly string[]).includes(value);
}

/**
 * Pick a locale from Accept-Language: the highest-ranked tag whose base
 * language the site actually publishes in wins, and anything else falls back
 * to Albanian. No IP geolocation — a visitor's address is not their language.
 */
function localeFromHeader(header: string | null): Locale {
  if (!header) return DEFAULT_LOCALE;

  const ranked = header
    .split(",")
    .map((part) => {
      const [tag, ...params] = part.trim().split(";");
      const q = params
        .map((p) => p.trim())
        .find((p) => p.startsWith("q="))
        ?.slice(2);
      return { tag: tag.trim().toLowerCase(), q: q ? Number(q) : 1 };
    })
    .filter((entry) => entry.tag.length > 0 && Number.isFinite(entry.q))
    .sort((a, b) => b.q - a.q);

  for (const { tag } of ranked) {
    const base = tag.split("-")[0];
    const matched = LOCALE_ALIASES[base];
    if (matched) return matched;
  }

  return DEFAULT_LOCALE;
}

export default function proxy(request: NextRequest) {
  const { pathname } = request.nextUrl;

  // 2 — the old asset and admin trees are gone.
  if (GONE_PREFIXES.some((prefix) => pathname.startsWith(prefix))) {
    return new NextResponse(null, {
      status: 410,
      headers: { "Cache-Control": "public, max-age=3600" },
    });
  }

  const segments = pathname.split("/").filter(Boolean);
  const [firstSegment, ...rest] = segments;

  // 3 — inside a locale tree, the registry decides.
  if (isLocale(firstSegment)) {
    if (resolveRoute(firstSegment, rest)) {
      return NextResponse.next();
    }

    const notFound = request.nextUrl.clone();
    notFound.pathname = `/${firstSegment}/404`;
    notFound.search = "";
    return NextResponse.rewrite(notFound, { status: 404 });
  }

  // 1 — the root redirects to a locale.
  if (pathname === "/") {
    const cookie = request.cookies.get(LOCALE_COOKIE)?.value;
    const locale = isLocale(cookie)
      ? cookie
      : localeFromHeader(request.headers.get("accept-language"));

    const url = request.nextUrl.clone();
    url.pathname = `/${locale}`;
    // 308 keeps the method and tells crawlers the move is permanent but the
    // root itself stays the canonical entry point.
    return NextResponse.redirect(url, 308);
  }

  // 4 — everything else that is not a locale path goes to the Albanian home.
  const url = request.nextUrl.clone();
  url.pathname = `/${DEFAULT_LOCALE}`;
  url.search = "";
  return NextResponse.redirect(url, 301);
}
