import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { RoleType } from "@/lib/enums/RoleType";
import { ACCESS_TOKEN_COOKIE, USER_DATA_COOKIE } from "@/lib/cookies";

const basePath = process.env.NEXT_PUBLIC_BASE_PATH || '';
const defaultLocale = 'en';
const supportedLocales = ['en', 'es'];
const LOCALE_COOKIE = 'NEXT_LOCALE';

const publicRoutes = ['/', '/login', '/signup', '/forgot-password', '/reset-password', '/contact', '/terms', '/privacy-policy', '/disclaimer', '/safety', '/refund', '/accept-invitation', '/verify-email', '/sample-report', '/individual/screening/verify', '/coming-soon', '/assessment', '/bibliography', '/cookie-policy'];
const authRoutes = ['/login', '/signup', '/forgot-password'];

const roleDashboards: Record<string, string> = {
  [RoleType.ADMIN]: '/admin',
  [RoleType.PRACTITIONERS]: '/practitioner',
  [RoleType.INDIVIDUALS]: '/individual',
};

const routeRoleMap: Record<string, string> = {
  '/admin': RoleType.ADMIN,
  '/practitioner': RoleType.PRACTITIONERS,
  '/individual': RoleType.INDIVIDUALS,
  '/practice-manager': RoleType.PRACTITIONERS,
};

function getUserData(request: NextRequest): { role: string; has_active_subscription?: boolean } | null {
  const token = request.cookies.get(ACCESS_TOKEN_COOKIE)?.value;
  const userData = request.cookies.get(USER_DATA_COOKIE)?.value;

  if (!token || !userData) {
    return null;
  }
  try {
    const parsed = JSON.parse(atob(userData));
    const rawRole = parsed.role || '';
    const role = rawRole.charAt(0).toUpperCase() + rawRole.slice(1);
    return { role, has_active_subscription: parsed.has_active_subscription };
  } catch {
    return null;
  }
}

function stripBase(path: string): string {
  return basePath && path.startsWith(basePath) ? path.slice(basePath.length) || '/' : path;
}

function getCleanPath(pathname: string): string {
  const path = stripBase(pathname);
  return path.match(/^\/(en|es)(\/|$)/) ? path.slice(3) || '/' : path;
}

function hasLocale(pathname: string): boolean {
  return /^\/(en|es)(\/|$)/.test(stripBase(pathname));
}

function isMatch(path: string, routes: string[]): boolean {
  return routes.some(r => path === r || (r !== '/' && path.startsWith(`${r}/`)));
}

function getLocaleFromRequest(request: NextRequest): string {
  // First check if there's a locale in the URL path
  const pathLocale = stripBase(request.nextUrl.pathname).match(/^\/(en|es)(\/|$)/)?.[1];
  if (pathLocale && supportedLocales.includes(pathLocale)) {
    return pathLocale;
  }

  // Then check the NEXT_LOCALE cookie
  const cookieLocale = request.cookies.get(LOCALE_COOKIE)?.value;
  if (cookieLocale && supportedLocales.includes(cookieLocale)) {
    return cookieLocale;
  }

  return defaultLocale;
}

function redirect(path: string, origin: string, locale: string): NextResponse {
  return NextResponse.redirect(new URL(`${basePath}/${locale}${path}`, origin));
}

function rewriteWithLocale(cleanPath: string, origin: string, locale: string): NextResponse {
  return NextResponse.rewrite(new URL(`${basePath}/${locale}${cleanPath === '/' ? '' : cleanPath}`, origin));
}

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

  // Skip internal routes
  if (pathNoBase.startsWith('/api') || pathNoBase.startsWith('/_next')) {
    return NextResponse.next();
  }

  const cleanPath = getCleanPath(pathname);
  const userData = getUserData(request);
  const userRole = userData?.role || null;
  const isLoggedIn = !!userRole;
  const locale = getLocaleFromRequest(request);

  // Logged in user on auth page -> redirect to dashboard
  if (isLoggedIn && isMatch(cleanPath, authRoutes)) {
    return redirect(roleDashboards[userRole] || '/', origin, locale);
  }

  // Public route -> add locale if needed
  if (isMatch(cleanPath, publicRoutes)) {
    return hasLocale(pathname) ? NextResponse.next() : rewriteWithLocale(cleanPath, origin, locale);
  }

  // Not logged in -> redirect to login
  if (!isLoggedIn) {
    // Only pass callbackUrl for valid internal paths (starts with / and no protocol)
    const safeCallback = cleanPath.startsWith('/') && !cleanPath.includes('://') ? cleanPath : '/';
    return NextResponse.redirect(new URL(`${basePath}/${locale}/login?callbackUrl=${encodeURIComponent(safeCallback)}`, origin));
  }

  // Invalid role -> redirect to login
  const dashboard = roleDashboards[userRole];
  if (!dashboard) {
    return redirect('/login', origin, locale);
  }

  // Role-based route protection
  for (const [route, required] of Object.entries(routeRoleMap)) {
    if (cleanPath.startsWith(route) && userRole !== required) {
      return redirect(dashboard, origin, locale);
    }
  }

  // Note: Practitioner subscription check is handled client-side in
  // app/[locale]/practitioner/layout.tsx which has billing history API fallback.
  // Do NOT add a server-side subscription redirect here — the cookie may be stale
  // while the billing API confirms an active subscription.

  // Add locale if needed
  return hasLocale(pathname) ? NextResponse.next() : rewriteWithLocale(cleanPath, origin, locale);
}

export const config = {
  matcher: [
    { source: '/' },
    '/((?!_next/static|_next/image|favicon.ico|.*\\.png$|.*\\.jpg$|.*\\.jpeg$|.*\\.gif$|.*\\.svg$|.*\\.ico$|.*\\.mp4$|.*\\.webm$|.*\\.mp3$|.*\\.wav$|.*\\.pdf$).*)',
  ],
};
