import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
import { getToken } from "next-auth/jwt"

import { Permissions } from "@/shared/types/permissions"

// Route prefix → minimum required permission
// Note: /admin/announcements is covered by /admin prefix (requires school:manage)
// Note: /announcements is accessible to all authenticated users (no permission entry needed)
const ROUTE_PERMISSIONS: Record<string, string> = {
  "/admin": Permissions.SCHOOL_MANAGE,
  "/teacher": Permissions.EXAM_READ,
  "/student": Permissions.HOMEWORK_SUBMIT,
  "/parent": Permissions.EXAM_READ,
  "/management": Permissions.GRADE_MANAGE,
}

// API route prefix → required permission
const API_PERMISSIONS: Record<string, string> = {
  "/api/ai/chat": Permissions.AI_CHAT,
}

function resolveDefaultPath(roles: string[]): string {
  if (roles.includes("admin")) return "/admin/dashboard"
  if (roles.includes("grade_head") || roles.includes("teaching_head")) return "/teacher/dashboard"
  if (roles.includes("teacher")) return "/teacher/dashboard"
  if (roles.includes("student")) return "/student/dashboard"
  if (roles.includes("parent")) return "/parent/dashboard"
  return "/dashboard"
}

// Next.js 16 renamed `middleware` to `proxy`.
// See: https://nextjs.org/docs/messages/middleware-to-proxy
export async function proxy(request: NextRequest) {
  const { pathname } = request.nextUrl

  // Skip static assets and auth pages
  if (
    pathname.startsWith("/_next") ||
    pathname.startsWith("/api/auth") ||
    pathname === "/login" ||
    pathname === "/register" ||
    pathname === "/favicon.ico"
  ) {
    return NextResponse.next()
  }

  const token = await getToken({
    req: request,
    secret: process.env.NEXTAUTH_SECRET,
  })

  // Not authenticated → redirect to login
  if (!token) {
    const loginUrl = new URL("/login", request.url)
    loginUrl.searchParams.set("callbackUrl", request.url)
    return NextResponse.redirect(loginUrl)
  }

  const permissions: string[] = (token.permissions as string[]) ?? []
  const roles: string[] = (token.roles as string[]) ?? []

  // Check API route permissions
  for (const [prefix, requiredPerm] of Object.entries(API_PERMISSIONS)) {
    if (pathname.startsWith(prefix)) {
      if (!permissions.includes(requiredPerm)) {
        return NextResponse.json({ error: "Forbidden" }, { status: 403 })
      }
      break
    }
  }

  // Check page route permissions
  for (const [prefix, requiredPerm] of Object.entries(ROUTE_PERMISSIONS)) {
    if (pathname.startsWith(prefix)) {
      if (!permissions.includes(requiredPerm)) {
        const defaultPath = resolveDefaultPath(roles)
        // Carry original path + reason in URL so the target page can explain
        // why the user was redirected (Web Interface Guidelines: URL reflects state).
        const redirectUrl = new URL(defaultPath, request.url)
        redirectUrl.searchParams.set("from", pathname)
        redirectUrl.searchParams.set("reason", "forbidden")
        return NextResponse.redirect(redirectUrl)
      }
      break
    }
  }

  return NextResponse.next()
}

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
}
