// app/api/contrats/route.ts
import { NextResponse } from "next/server";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies, headers } from "next/headers";
import { resolveActiveOrg } from "@/lib/resolveActiveOrg";
import { createClient } from '@supabase/supabase-js';
import { detectDemoModeFromHeaders } from "@/lib/demo-detector";
import { DEMO_CONTRACTS, DEMO_ORGANIZATION } from "@/lib/demo-data";
import { getUserPermissions, canAccessContrats, checkPermissionOrRespond } from "@/lib/permissions";

// Force dynamic rendering and disable revalidation cache for this proxy
export const dynamic = 'force-dynamic';
export const revalidate = 0;
export const runtime = 'nodejs';

const UPSTREAM_BASE =
  process.env.STRUCTURE_API_BASE_URL ||
  "https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default";
const PATH_PREFIX = process.env.STRUCTURE_API_PATH_PREFIX ?? "";

function buildUpstreamUrl(req: Request) {
  const url = new URL(req.url);
  const upstream = new URL(UPSTREAM_BASE + `${PATH_PREFIX}/contrats`);
  // Rejoue tous les query params vers l'amont
  url.searchParams.forEach((v, k) => upstream.searchParams.set(k, v));
  return upstream;
}

export async function GET(req: Request) {
  // 🎭 Vérification du mode démo en premier
  const h = headers();
  const isDemoMode = detectDemoModeFromHeaders(h);
  
  if (isDemoMode) {
    console.log("🎭 [API CONTRATS] Mode démo détecté - renvoi de données fictives");
    
    const url = new URL(req.url);
    const regime = url.searchParams.get("regime");
    const status = url.searchParams.get("status");
    const page = parseInt(url.searchParams.get("page") || "1");
    const limit = parseInt(url.searchParams.get("limit") || "10");
    
    // Filtrer les contrats selon les paramètres
    let filteredContracts = DEMO_CONTRACTS;
    
    if (regime === "CDDU") {
      filteredContracts = filteredContracts.filter(c => 
        c.regime === "CDDU_MONO" || c.regime === "CDDU_MULTI"
      );
    } else if (regime === "RG") {
      filteredContracts = filteredContracts.filter(c => c.regime === "RG");
    }
    
    if (status === "en_cours") {
      filteredContracts = filteredContracts.filter(c => 
        c.etat === "en_cours" || c.etat === "signe"
      );
    } else if (status === "termines") {
      filteredContracts = filteredContracts.filter(c => 
        c.etat === "traitee"
      );
    }
    
    // Pagination
    const startIndex = (page - 1) * limit;
    const endIndex = startIndex + limit;
    const paginatedContracts = filteredContracts.slice(startIndex, endIndex);
    
    return NextResponse.json({
      items: paginatedContracts,
      total: filteredContracts.length,
      page,
      limit,
      totalPages: Math.ceil(filteredContracts.length / limit),
      hasMore: endIndex < filteredContracts.length
    });
  }

  try {
    const sb = createRouteHandlerClient({ cookies });
    
    // 🔒 VÉRIFICATION DES PERMISSIONS (bloquer COMPTA)
    const permissions = await getUserPermissions(sb);
    const permissionCheck = canAccessContrats(permissions);
    const errorResponse = checkPermissionOrRespond(permissionCheck);
    if (errorResponse) return errorResponse;
    
    const url = new URL(req.url);
    const regime = url.searchParams.get("regime");
    // Si CDDU, RG, ou absence de regime (= tous), lire depuis Supabase (table cddu_contracts)
    if (regime === "CDDU" || regime === "RG" || !regime) {
      const sb = createRouteHandlerClient({ cookies });
      // Use centralized resolver which normalizes header/cookie values like 'unknown'
      // and implements staff null-org semantics (returns null for global staff access).
      const orgId = await resolveActiveOrg(sb);
      
      // If orgId is not found here it means either the user is a staff with no active org
      // or the resolution failed. For staff we want to allow global access (orgId === null).
      // For non-staff users, absence of orgId will result in an empty result set later.
      // Pagination
      const page = parseInt(url.searchParams.get("page") || "1", 10);
      const limit = parseInt(url.searchParams.get("limit") || "10", 10);
      const offset = (page - 1) * limit;
      // Recherche
      const q = url.searchParams.get("q")?.trim();
      // Tri
      const sort = url.searchParams.get("sort") || "date_fin";
      const order = url.searchParams.get("order") || "desc";
      // Support explicit org filter via query param `org_id` (sent by client UI when staff selects a structure).
      // Resolution priority:
      // 1) If `org_id` query param is present, allow it only for staff or if it matches resolved orgId for non-staff.
      // 2) Else if resolved orgId is present, scope to it.
      // 3) Else resolved orgId === null -> staff global access: use admin client to read all rows.
      const requestedOrg = url.searchParams.get("org_id") || undefined;
      let query: any;

      // Helper: determine if this is a staff user. Note: resolveActiveOrg may return an org id
      // when the UI set a header/cookie; however the current session user may still be a staff
      // account. We therefore explicitly check the session to detect staff privileges so that
      // staff users who provided an explicit org can still be handled via the admin client.
      let detectedIsStaff = false;
      try {
        const { data: { session } } = await sb.auth.getSession();
        if (session) {
          try {
            const { data: staffRow } = await sb.from('staff_users').select('is_staff').eq('user_id', session.user.id).maybeSingle();
            detectedIsStaff = !!(staffRow as any)?.is_staff;
          } catch {
            const userMeta = session.user?.user_metadata || {};
            const appMeta = session.user?.app_metadata || {};
            detectedIsStaff = Boolean((userMeta.is_staff === true || userMeta.role === 'staff') || (Array.isArray(appMeta.roles) && appMeta.roles.includes('staff')));
          }
        }
      } catch {
        detectedIsStaff = false;
      }

      // Consider the caller as staff if either resolveActiveOrg returned null (explicit staff global)
      // or the session indicates staff privileges.
      const isStaff = orgId === null || detectedIsStaff;

      // Prepare admin client for staff reads (bypass RLS) if possible
      let admin: any = null;
      if (isStaff) {
        if (!process.env.NEXT_PUBLIC_SUPABASE_URL || !process.env.SUPABASE_SERVICE_ROLE_KEY) {
          console.error('Service role key not configured; cannot perform staff admin reads');
          // we'll still try to use sb but results may be restricted
        } else {
          admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!, {
            auth: { autoRefreshToken: false, persistSession: false },
          });
        }
      }

      if (requestedOrg) {
        // If non-staff provided a requestedOrg, ensure it matches their resolved orgId
        if (!isStaff && orgId && requestedOrg !== orgId) {
          return NextResponse.json({ items: [], page, limit, hasMore: false });
        }
        // Staff should use admin client to bypass RLS when filtering by a specific org
        if (isStaff && admin) {
          query = admin.from("cddu_contracts").select("*, organizations!inner(name), payslips(id, processed)").eq("org_id", requestedOrg);
        } else {
          query = sb.from("cddu_contracts").select("*, organizations!inner(name), payslips(id, processed)").eq("org_id", requestedOrg);
        }
      } else if (orgId) {
        if (isStaff && admin) {
          query = admin.from("cddu_contracts").select("*, organizations!inner(name), payslips(id, processed)").eq("org_id", orgId);
        } else {
          query = sb.from("cddu_contracts").select("*, organizations!inner(name), payslips(id, processed)").eq("org_id", orgId);
        }
      } else {
        // orgId === null and no requestedOrg -> staff global read required
        if (!isStaff) {
          return NextResponse.json({ items: [], page, limit, hasMore: false });
        }
        if (!admin) {
          console.error('Service role key not configured; cannot perform staff global read');
          return NextResponse.json({ items: [], page, limit, hasMore: false });
        }
        query = admin.from("cddu_contracts").select("*, organizations!inner(name), payslips(id, processed)");
      }
      // We'll fetch rows then filter in JS to avoid brittle SQL patterns (accents/variants)
      if (q) {
        query = query.or(`employee_name.ilike.%${q}%,contract_number.ilike.%${q}%,production_name.ilike.%${q}%`);
      }
      // On ne filtre plus par statut SQL, mais par date de fin côté Node.js
      // TODO: Filtres période/année/mois si besoin
      query = query.order("created_at", { ascending: false });
      const { data, error } = await query;
      if (error) return NextResponse.json({ error: error.message }, { status: 500 });
      // If caller asked for debug resolution, return org resolution info + raw row count
      const debugResolve = url.searchParams.get("debug_resolve");
      if (debugResolve === "1") {
        const resolvedSource = req.headers.get("x-active-org-id") ? "header" : cookies().get("active_org_id") ? "cookie" : "session-db";
        return NextResponse.json({ resolved: { orgId, resolvedSource }, rows: (data || []).length, sample: (data || []).slice(0, 3) });
      }
  // Filtrage JS selon la date de fin, année, période, puis tri du plus récent au plus ancien
      const status = url.searchParams.get("status");
      const today = new Date();
      today.setHours(0,0,0,0); // UTC minuit
      const year = url.searchParams.get("year") ? parseInt(url.searchParams.get("year")!, 10) : undefined;
      // Prise en compte des paramètres month, quarter, semester, period
      const month = url.searchParams.get("month") ? parseInt(url.searchParams.get("month")!, 10) : undefined;
      const quarter = url.searchParams.get("quarter") ? parseInt(url.searchParams.get("quarter")!, 10) : undefined;
      const semester = url.searchParams.get("semester") ? parseInt(url.searchParams.get("semester")!, 10) : undefined;
      const period = url.searchParams.get("period") || "Y";
      // Helper pour filtrer par période
      function isInPeriod(date: Date) {
        if (!year) return true;
        if (date.getFullYear() !== year) return false;
        if (typeof month === "number") {
          return date.getMonth() + 1 === month;
        } else if (typeof quarter === "number") {
          // Trimestres : Q1=janv-mars, Q2=avr-juin, Q3=juil-sept, Q4=oct-déc
          if (quarter === 1) return date.getMonth() >= 0 && date.getMonth() <= 2;
          if (quarter === 2) return date.getMonth() >= 3 && date.getMonth() <= 5;
          if (quarter === 3) return date.getMonth() >= 6 && date.getMonth() <= 8;
          if (quarter === 4) return date.getMonth() >= 9 && date.getMonth() <= 11;
        } else if (typeof semester === "number") {
          // Semestres : S1=janv-juin, S2=juil-déc
          if (semester === 1) return date.getMonth() >= 0 && date.getMonth() <= 5;
          if (semester === 2) return date.getMonth() >= 6 && date.getMonth() <= 11;
        } else if (period.startsWith("M")) {
          const m = parseInt(period.slice(1), 10);
          return date.getMonth() + 1 === m;
        } else if (period.startsWith("Q")) {
          const q = parseInt(period.slice(1), 10);
          if (q === 1) return date.getMonth() >= 0 && date.getMonth() <= 2;
          if (q === 2) return date.getMonth() >= 3 && date.getMonth() <= 5;
          if (q === 3) return date.getMonth() >= 6 && date.getMonth() <= 8;
          if (q === 4) return date.getMonth() >= 9 && date.getMonth() <= 11;
        } else if (period.startsWith("S")) {
          const s = parseInt(period.slice(1), 10);
          if (s === 1) return date.getMonth() >= 0 && date.getMonth() <= 5;
          if (s === 2) return date.getMonth() >= 6 && date.getMonth() <= 11;
        }
        // "Y" ou autre : toute l'année
        return true;
      }
      let filtered = (data || []).filter((row: any) => {
        const end = row.end_date || row.date_fin;
        
        // Pour les CDI (pas de date de fin), toujours les considérer comme "en_cours"
        if (!end) {
          if (status === "en_cours") return true;
          if (status === "termines") return false;
          return true;
        }
        
        const endDate = new Date(end);
        if (isNaN(endDate.getTime())) return false;
        endDate.setHours(0,0,0,0);
        if (status === "en_cours") {
          // Un contrat est "en_cours" si sa date de fin est dans le futur ou aujourd'hui
          // Cela inclut les contrats qui n'ont pas encore commencé (date_debut future)
          return endDate >= today;
        } else if (status === "termines") {
          if (endDate < today && isInPeriod(endDate)) return true;
          return false;
        }
        return true;
      });
      // Filter by requested regime: if caller asked for RG, keep only rows where type_d_embauche indicates RG
      // If caller asked for CDDU, exclude RG rows so they don't appear in CDDU tab
      // If no regime specified, keep all rows (CDDU + RG)
      const normalize = (s: any) => String(s || '').toLowerCase();
      if (regime === 'RG') {
        filtered = filtered.filter((row: any) => {
          const td = normalize(row.type_d_embauche);
          const tc = normalize(row.type_de_contrat);
          // Inclure les contrats avec type_d_embauche = "Régime général" OU type_de_contrat = "CDI"
          return td.includes('régime général') || td.includes('regime general') || td === 'rg' || tc === 'cdi';
        });
      } else if (regime === 'CDDU') {
        filtered = filtered.filter((row: any) => {
          const td = normalize(row.type_d_embauche);
          const tc = normalize(row.type_de_contrat);
          // Exclure les contrats RG et CDI de l'onglet CDDU
          return !(td.includes('régime général') || td.includes('regime general') || td === 'rg' || tc === 'cdi');
        });
      }
      // Si regime === null/undefined, on garde tous les contrats (pas de filtrage)
      // Tri basé sur les paramètres sort/order
      filtered.sort((a: any, b: any) => {
        let aValue: any;
        let bValue: any;
        
        // Déterminer le champ à trier
        if (sort === 'date_debut' || sort === 'start_date') {
          aValue = new Date(a.start_date || a.date_debut || 0);
          bValue = new Date(b.start_date || b.date_debut || 0);
        } else {
          // Défaut: date_fin
          aValue = new Date(a.end_date || a.date_fin || 0);
          bValue = new Date(b.end_date || b.date_fin || 0);
        }
        
        // Appliquer l'ordre
        const comparison = aValue.getTime() - bValue.getTime();
        return order === 'asc' ? comparison : -comparison;
      });
      // Pagination JS après filtrage/tri
      const paged = filtered.slice(offset, offset + limit);
      // Mapping format attendu par le front
      const items = paged.map((row: any) => {
        const isMulti = row.multi_mois === "Oui" || row.multi_mois === true;
        const td = String(row.type_d_embauche || "").toLowerCase();
        const tc = String(row.type_de_contrat || "").toLowerCase();
        const isRG = td.includes("régime général") || td.includes("regime general") || td === "rg" || tc === "cdi";
        
        // Déterminer l'état à afficher
        let displayEtat = (row.etat_de_la_demande || row.etat || "en_cours");
        
        // Pour les contrats terminés (status === "termines")
        if (status === "termines") {
          if (isMulti) {
            // CDDU multi-mois terminé : afficher "Terminé"
            displayEtat = "traitee"; // ou créer un nouvel état "termine" si besoin
          } else {
            // CDDU mono-mois terminé : afficher l'état de traitement de la payslip
            const payslips = row.payslips || [];
            if (payslips.length > 0) {
              // Prendre la première payslip (mono-mois = une seule paie)
              const payslip = payslips[0];
              if (payslip.processed === true) {
                displayEtat = "traitee";
              } else {
                displayEtat = "en_cours";
              }
            } else {
              // Pas de payslip créée
              displayEtat = "en_cours";
            }
          }
        }
        
        return {
          id: row.id,
          reference: row.contract_number,
          salarie_nom: row.employee_name,
          production: row.production_name || row.organizations?.name || "",
          // Expose organization info (if available) so UI can show "Structure" column for staff
          org_id: row.org_id || null,
          org_name: row.organizations?.name || null,
          profession: row.profession || row.role || "",
          date_debut: row.start_date,
          date_fin: row.end_date,
          etat: displayEtat,
          is_multi_mois: isMulti,
          regime: isRG ? (tc === "cdi" ? "CDI" : "RG") : (isMulti ? "CDDU_MULTI" : "CDDU_MONO"),
        };
      });
      return NextResponse.json({
        items,
        page,
        limit,
        hasMore: filtered.length > offset + limit,
        total: filtered.length,
        totalPages: Math.ceil(filtered.length / limit),
        debug: {
          orgId,
          isStaff,
          totalRowsFromDB: (data || []).length,
          filteredRows: filtered.length,
          returnedItems: items.length
        }
      });
    }
    // Sinon, proxy comme avant (RG ou autre)
    const upstream = buildUpstreamUrl(req);
    const debug = url.searchParams.get("debug");
    if (debug === "1") {
      const activeOrg = req.headers.get("x-active-org-id") || undefined;
      const companyNameB64 = req.headers.get("x-company-name-b64") || undefined;
      const companyKey = req.headers.get("x-company-key") || undefined;
      const rawCompanyName = req.headers.get("x-company-name") || undefined;
      const incomingAuth = req.headers.get("authorization") || undefined;
      return NextResponse.json({
        upstream: upstream.toString(),
        forwardedHeaders: {
          ...(activeOrg ? { "x-active-org-id": activeOrg } : {}),
          ...(companyNameB64 ? { "x-company-name-b64": companyNameB64 } : {}),
          ...(rawCompanyName ? { "x-company-name": rawCompanyName } : {}),
          ...(companyKey ? { "x-company-key": companyKey } : {}),
          ...(incomingAuth ? { authorization: incomingAuth } : {}),
          ...(process.env.STRUCTURE_API_TOKEN && !incomingAuth
            ? { authorization: `Bearer ${process.env.STRUCTURE_API_TOKEN?.slice(0, 8)}…` }
            : {}),
        },
        note: "Set STRUCTURE_API_BASE_URL and optionally STRUCTURE_API_PATH_PREFIX (default '/api').",
      });
    }
    const activeOrg = req.headers.get("x-active-org-id") || undefined;
    const companyNameB64 = req.headers.get("x-company-name-b64") || undefined;
    const companyKey = req.headers.get("x-company-key") || undefined;
    const rawCompanyName = req.headers.get("x-company-name") || undefined;
    const incomingAuth = req.headers.get("authorization") || undefined;

    const r = await fetch(upstream.toString(), {
      method: "GET",
      headers: {
        Accept: "application/json",
        ...(activeOrg ? { "x-active-org-id": activeOrg } : {}),
        ...(companyNameB64 ? { "x-company-name-b64": companyNameB64 } : {}),
        ...(rawCompanyName ? { "x-company-name": rawCompanyName } : {}),
        ...(companyKey ? { "x-company-key": companyKey } : {}),
        ...(incomingAuth ? { Authorization: incomingAuth } : {}),
        ...(process.env.STRUCTURE_API_TOKEN && !incomingAuth
          ? { Authorization: `Bearer ${process.env.STRUCTURE_API_TOKEN}` }
          : {}),
      },
      cache: "no-store",
    });

    const ct = r.headers.get("content-type") || "application/json";
    const body = await r.text();

    if (!r.ok) {
      return new NextResponse(body || JSON.stringify({ error: "upstream_failed" }), {
        status: r.status,
        headers: { "content-type": ct },
      });
    }

    return new NextResponse(body, {
      status: 200,
      headers: { "content-type": ct },
    });
  } catch (e: any) {
    // En cas de panne réseau ou d'URL invalide, renvoyer une erreur JSON claire
    return NextResponse.json(
      { error: "proxy_error", message: e?.message || String(e) },
      { status: 500 }
    );
  }
}