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

import { canAccessPath, getDefaultPathForRole, parseSessionCookie, SESSION_COOKIE, type UserRole } from "@/lib/auth";
import { DEFAULT_LOCALE, isLocale, LOCALE_COOKIE } from "@/lib/i18n";

const publicPaths = ["/login", "/forgot-password", "/reset-password", "/unauthorized", "/invite", "/auth"];

function isPublicPath(pathname: string) {
  return publicPaths.some((path) => pathname === path || pathname.startsWith(`${path}/`));
}

async function decodeSessionCookie(value: string) {
  return (await parseSessionCookie(value)) as null | { role: UserRole };
}

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;
  const response = NextResponse.next();

  if (pathname.startsWith("/_next") || pathname.includes(".")) {
    return response;
  }

  const sessionCookie = request.cookies.get(SESSION_COOKIE)?.value;
  const session = sessionCookie ? await decodeSessionCookie(sessionCookie) : null;
  const localeCookie = request.cookies.get(LOCALE_COOKIE)?.value;
  const acceptLanguage = request.headers.get("accept-language")?.toLowerCase() || "";

  if (!localeCookie) {
    const detected = acceptLanguage.includes("id") ? "id" : acceptLanguage.includes("en") ? "en" : DEFAULT_LOCALE;
    response.cookies.set(LOCALE_COOKIE, detected, {
      path: "/",
      maxAge: 365 * 24 * 60 * 60,
      secure: process.env.NODE_ENV === "production",
      sameSite: "lax"
    });
  } else if (!isLocale(localeCookie)) {
    response.cookies.set(LOCALE_COOKIE, DEFAULT_LOCALE, {
      path: "/",
      maxAge: 365 * 24 * 60 * 60,
      secure: process.env.NODE_ENV === "production",
      sameSite: "lax"
    });
  }

  if (!session && !isPublicPath(pathname) && pathname !== "/") {
    const loginUrl = new URL("/login", request.url);
    loginUrl.searchParams.set("next", pathname);
    return NextResponse.redirect(loginUrl);
  }

  if (session && (pathname === "/" || pathname === "/login")) {
    return NextResponse.redirect(new URL(getDefaultPathForRole(session.role), request.url));
  }

  if (session && !isPublicPath(pathname) && !canAccessPath(session.role, pathname)) {
    return NextResponse.redirect(new URL("/unauthorized", request.url));
  }

  return response;
}

export const config = {
  matcher: ["/((?!api).*)"]
};
