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

import {
  AUTH_COOKIE_NAME,
  AUTH_ROLE_COOKIE_NAME,
  canAccessAdminArea,
  canRoleOpenPath,
  canRoleUseApp,
  getRoleHomePath,
  isUserRole,
} from "@/features/auth/auth-data";

const LOGIN_PATH = "/auth/login";

function redirectTo(path: string, request: NextRequest) {
  return NextResponse.redirect(new URL(path, request.url));
}

function redirectToLogin(request: NextRequest) {
  return redirectTo(LOGIN_PATH, request);
}

function isAdminArea(pathname: string) {
  return pathname === "/admin" || pathname.startsWith("/admin/");
}

export function proxy(request: NextRequest) {
  const { pathname } = request.nextUrl;
  const isLoggedIn = request.cookies.get(AUTH_COOKIE_NAME)?.value === "true";
  const roleValue = request.cookies.get(AUTH_ROLE_COOKIE_NAME)?.value;
  const role = isUserRole(roleValue) ? roleValue : undefined;
  const canUseApp = role ? canRoleUseApp(role) : false;

  if (pathname === "/") {
    return isLoggedIn && role && canUseApp
      ? redirectTo(getRoleHomePath(role) ?? LOGIN_PATH, request)
      : redirectToLogin(request);
  }

  if (pathname.startsWith("/auth")) {
    if (isLoggedIn && role && canUseApp) {
      return redirectTo(getRoleHomePath(role) ?? LOGIN_PATH, request);
    }

    return NextResponse.next();
  }

  // Everything else matched by `config` is a protected app area.
  if (!isLoggedIn || !role || !canUseApp) {
    return redirectToLogin(request);
  }

  // Admin area is permission-gated (today: Administrator only).
  if (isAdminArea(pathname)) {
    return canAccessAdminArea(role)
      ? NextResponse.next()
      : redirectTo(getRoleHomePath(role) ?? LOGIN_PATH, request);
  }

  if (!canRoleOpenPath(role, pathname)) {
    return redirectTo(getRoleHomePath(role) ?? LOGIN_PATH, request);
  }

  return NextResponse.next();
}

export const config = {
  matcher: [
    "/",
    "/auth/:path*",
    "/admin/:path*",
    "/pswg/:path*",
    "/ministry/:path*",
    "/account-setting/:path*",
  ],
};
