// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { createMiddlewareClient } from "@supabase/auth-helpers-nextjs";
import { detectDemoMode, logDemoMode } from "@/lib/demo-detector";

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL || "";
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || process.env.SUPABASE_ANON_KEY || "";

// Pages de l'Espace Paie nécessitant une session authentifiée
const PROTECTED = [
  "/contrats",
  "/contrats-multi",
  "/contrats-rg",
  "/salaries",
  "/cotisations",
  "/facturation",
  "/virements-salaires",
  "/vos-documents",
  "/vos-acces",
  "/informations",
  "/compte",
  "/support",
  "/signatures-electroniques",
  "/staff",
  "/debug",
];

export async function middleware(req: NextRequest) {
  // Toujours créer une réponse et rafraîchir la session en amont
  const res = NextResponse.next();

  if (!supabaseUrl || !supabaseAnonKey) {
    console.error("[Middleware] Supabase env manquantes", {
      hasUrl: Boolean(supabaseUrl),
      hasAnonKey: Boolean(supabaseAnonKey),
      note: "Vérifie .env.local (à la racine du projet) et redémarre le serveur"
    });
    // On retourne la réponse sans tenter de lire la session (évite le crash en dev)
    return res;
  }

  // 1) Rafraîchit les cookies de session si nécessaire (very important)
  const supabase = createMiddlewareClient({ req, res }, { supabaseUrl, supabaseKey: supabaseAnonKey });
  const { data: { session } } = await supabase.auth.getSession();

  // 1.5) Maintenir les cookies persistants si rememberMe est activé
  const rememberMeCookie = req.cookies.get("remember_me");
  if (session && rememberMeCookie?.value === "true") {
    // Prolonger la durée des cookies Supabase à chaque requête
    const cookieOptions = {
      maxAge: 60 * 60 * 24 * 30, // 30 jours
      path: "/",
      sameSite: "lax" as const,
      httpOnly: true,
      secure: process.env.NODE_ENV === "production",
    };

    // Récupérer tous les cookies Supabase et les renouveler
    req.cookies.getAll().forEach((cookie) => {
      if (cookie.name.startsWith("sb-")) {
        res.cookies.set(cookie.name, cookie.value, cookieOptions);
      }
    });

    // Renouveler aussi le cookie remember_me
    res.cookies.set("remember_me", "true", cookieOptions);
  }

  const path = req.nextUrl.pathname;
  const isStaticFile = /\.[^/]+$/.test(path); // ex: /odentas-logo.png, /robots.txt, etc.

  // 2) Vérification du mode maintenance
  // Éviter de vérifier sur les API calls, assets, la page maintenance elle-même, la page de connexion,
  // et les pages publiques (auto-declaration, dl-contrat-signe, signature-salarie, politique-confidentialite, mentions-legales)
  const isApiOrAssets = path.startsWith('/api') || path.startsWith('/_next') || 
                       path.startsWith('/favicon') || path.startsWith('/public') || isStaticFile;
  const isMaintenancePage = path === '/maintenance';
  const isSigninPage = path === '/signin';
  const isPublicPage = path.startsWith('/auto-declaration') || 
                       path.startsWith('/dl-contrat-signe') || 
                       path.startsWith('/signature-salarie') ||
                       path === '/politique-confidentialite' ||
                       path === '/mentions-legales' ||
                       path === '/activate';

  // Ne pas impacter l'environnement local/dev par le mode maintenance
  const hostname = req.nextUrl.hostname || '';
  const isDevEnv = process.env.NODE_ENV === 'development';
  const isLocalHost = hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname.endsWith('.local');
  // Optionnel: IP privée (LAN) → considérer comme non-prod
  const isPrivateIp = /^10\./.test(hostname) || /^192\.168\./.test(hostname) || /^172\.(1[6-9]|2\d|3[0-1])\./.test(hostname);
  const skipMaintenance = isDevEnv || isLocalHost || isPrivateIp;

  if (!skipMaintenance && !isApiOrAssets && !isMaintenancePage && !isSigninPage && !isPublicPage) {
    try {
      // Vérifier le statut de maintenance
      const { data: maintenanceStatus } = await supabase
        .from("maintenance_status")
        .select("is_maintenance_mode")
        .single();

      if (maintenanceStatus?.is_maintenance_mode) {
        // Vérifier si l'utilisateur est staff
        let isStaff = false;
        if (session?.user) {
          const { data: staffData } = await supabase
            .from("staff_users")
            .select("is_staff")
            .eq("user_id", session.user.id)
            .maybeSingle();
          
          isStaff = !!staffData?.is_staff;
        }

        // Si pas staff, rediriger vers la page maintenance
        if (!isStaff) {
          const url = req.nextUrl.clone();
          url.pathname = "/maintenance";
          return NextResponse.redirect(url);
        }
      }
    } catch (error) {
      console.error("Erreur lors de la vérification de maintenance:", error);
      // En cas d'erreur, on continue sans bloquer
    }
  }

  // 3) Si on essaie d'aller sur /maintenance mais qu'on n'est pas en maintenance
  if (isMaintenancePage && !skipMaintenance) {
    try {
      const { data: maintenanceStatus } = await supabase
        .from("maintenance_status")
        .select("is_maintenance_mode")
        .single();

      // Si pas en maintenance, rediriger vers l'accueil
      if (!maintenanceStatus?.is_maintenance_mode) {
        const url = req.nextUrl.clone();
        url.pathname = "/";
        return NextResponse.redirect(url);
      }
    } catch (error) {
      console.error("Erreur lors de la vérification de maintenance:", error);
    }
  }

  // 4) Staff status verification (DB-first, then fallback to metadata like /api/me)
  let isStaff = false;
  if (session?.user?.id) {
    try {
      // Try DB first (same logic as /api/me)
      const { data } = await supabase
        .from("staff_users")
        .select("is_staff")
        .eq("user_id", session.user.id)
        .maybeSingle();
      isStaff = !!data?.is_staff;
    } catch (e) {
      // fallback to token metadata
      isStaff = Boolean(
        (session.user.user_metadata && (session.user.user_metadata.is_staff === true || session.user.user_metadata.role === 'staff')) ||
        (session.user.app_metadata && Array.isArray((session.user.app_metadata as any).roles) && (session.user.app_metadata as any).roles.includes('staff'))
      );
    }
  }

  // 4.1) Guard: restrict access to table entry route to staff only (temporary feature flag)
  if (path.startsWith('/contrats/nouveau/saisie-tableau') && !isStaff) {
    const url = req.nextUrl.clone();
    url.pathname = '/contrats';
    return NextResponse.redirect(url);
  }

  if (!isStaff) {
    // Si un cookie staff "active_org_id" existe, purge-le pour éviter les fuites d'org côté client
    const hasLegacy = req.cookies.get('active_org_id');
    if (hasLegacy) {
      res.cookies.set('active_org_id', '', { path: '/', maxAge: 0 });
      res.cookies.set('active_org_id', '', { path: '/staff', maxAge: 0 });
    }
  }

  // 5) Vérification du mode démo avant l'authentification
  const isDemoMode = detectDemoMode(req);
  
  // Si en mode démo, ajouter un header pour indiquer au layout de contourner l'auth
  if (isDemoMode) {
    res.headers.set('x-demo-mode', 'true');
    logDemoMode(true, 'MIDDLEWARE', req);
  }

  // 6) Gate des pages protégées (laisse passer API & assets)
  const needsAuth = PROTECTED.some((p) => path.startsWith(p));

  // Contourner l'authentification si en mode démo
  if (needsAuth && !session && !isDemoMode) {
    const url = req.nextUrl.clone();
    url.pathname = "/signin";
    url.searchParams.set("next", path);
    return NextResponse.redirect(url);
  }

  // Important : retourner *res* (celui modifié par auth-helpers)
  return res;
}

// Évite d'exécuter le middleware sur les assets Next
export const config = {
  matcher: [
    // Exclure: assets Next, favicon et tout fichier avec extension (images, css, js, etc.)
    "/((?!_next/static|_next/image|favicon.ico|public|.*\\..*).*)",
  ],
};
