import { NextResponse, NextRequest } from 'next/server'
import { JWTPayload, jwtVerify } from 'jose'

interface DecodedJwtPayload extends JWTPayload {
  role: string
}

interface RedirectRule {
  source_path: string
  destination_path: string
  redirect_type: number
}

interface NewRedirectRule {
    data: RedirectRule[]
}

/* ======================================================
   Redirect cache (DB / service driven)
====================================================== */
let redirectCache: Map<string, RedirectRule> | null = null
let lastFetched = 0
const CACHE_TTL = 3_600_000 // 1 hour

async function getRedirects(): Promise<Map<string, RedirectRule>> {
  const now = Date.now()

  if (redirectCache && now - lastFetched < CACHE_TTL) {
    return redirectCache
  }

  try {
    const res = await fetch(
      `${process.env.NEXTAUTH_URL}/api/frontend/redirects`,
      { cache: 'no-store' }
    )

    if (!res.ok) return new Map()

    const data: NewRedirectRule = await res.json()

    redirectCache = new Map(
      data.data.map(r => [
        r.source_path.replace(/\/$/, '').replace(/-$/, ''),
        {
          source_path: r.source_path.replace(/\/$/, ''),
          destination_path: r.destination_path,
          redirect_type: r.redirect_type,
        },
      ])
    )

    lastFetched = now
    return redirectCache
  } catch {
    return new Map()
  }
}

/* ======================================================
   Middleware
====================================================== */
export async function middleware(request: NextRequest) {
  const url = request.nextUrl.clone()
  const pathname = url.pathname.replace(/\/$/, '')

  /* ======================================================
     STEP 1: DB / CMS redirects (NEW — added, not replacing)
  ====================================================== */
  try {
    const redirects = await getRedirects()
    const rule = redirects.get(pathname)

    if (rule && rule.destination_path !== pathname) {
      const redirectUrl = new URL(rule.destination_path, request.url)
      redirectUrl.search = url.search
      return NextResponse.redirect(redirectUrl, rule.redirect_type)
    }
  } catch {
    // fail open
  }

  /* ======================================================
     STEP 2: YOUR EXISTING HARD-CODED REGEX REDIRECT (UNCHANGED)
  ====================================================== */
  const applyCoursesPattern = /^\/apply-for-course\/([^\/\?]+)(\/.*)?$/

  if (applyCoursesPattern.test(pathname)) {
    const match = pathname.match(applyCoursesPattern)
    if (match && match[1]) {
      const courseId = match[1]
      const newPathname = `/courses/${courseId}${match[2] || ''}`
      const newUrl = new URL(newPathname, request.url)
      newUrl.search = url.search
      return NextResponse.redirect(newUrl, 301)
    }
  }

  /* ======================================================
     STEP 3: YOUR EXISTING AUTH LOGIC (UNCHANGED)
  ====================================================== */
  const token = request.cookies.get('university-token')?.value

  if (request.nextUrl.pathname.startsWith('/api/frontend/')) {
    return NextResponse.next()
  }

  if (request.nextUrl.pathname.startsWith('/api')) {
    if (!token) {
      return NextResponse.json({ message: 'Unauthorized' }, { status: 401 })
    }

    try {
      const secret = new TextEncoder().encode(process.env.JWT_SECRET)
      const decoded = await jwtVerify<DecodedJwtPayload>(token, secret)
      const role = decoded.payload.role
      const userId = decoded.payload.id

      console.log(`API Access: ${role} (${userId}) → ${request.nextUrl.pathname}`)

      if (request.nextUrl.pathname.startsWith('/api/internal')) {
        const allowed = ['admin', 'foreign-student']
        if (!allowed.includes(role)) {
          return NextResponse.json({ message: 'Forbidden' }, { status: 403 })
        }
      }

      return NextResponse.next()
    } catch {
      return NextResponse.json({ message: 'Unauthorized' }, { status: 401 })
    }
  }

    if (pathname.startsWith("/admin") || pathname.startsWith("/dashboard") || pathname.startsWith("/consultant-dashboard") || pathname.startsWith("/foreign-student-dashboard")) 
    {

        if (!token) {
            return NextResponse.redirect(new URL('/student-login', request.url))
        }

        try {
            const secret = new TextEncoder().encode(process.env.JWT_SECRET)
            const decoded = await jwtVerify<DecodedJwtPayload>(token, secret)
            const role = decoded.payload.role
            const path = request.nextUrl.pathname

            if (path.startsWith('/admin') && role !== 'admin') {
                return NextResponse.redirect(new URL('/student-login', request.url))
            }

            if (path.startsWith('/dashboard') && role !== 'student') {
                return NextResponse.redirect(new URL('/student-login', request.url))
            }

            if (path.startsWith('/consultant-dashboard') && role !== 'consultant') {
                return NextResponse.redirect(new URL('/consultant-login', request.url))
            }

            if (
                path.startsWith('/foreign-student-dashboard') &&
                role !== 'foreign-student'
            ) {
                return NextResponse.redirect(
                    new URL('/foreign-students/login', request.url)
                )
            }

            return NextResponse.next()
        } catch {
            return NextResponse.redirect(new URL('/student-login', request.url))
        }
    }

    return NextResponse.next();
}

/* ======================================================
   Matcher (UNCHANGED)
====================================================== */
export const config = {
  matcher: [
    "/((?!api|trpc|_next|_vercel|.*\\..*).*)"
  ]
}
