import { NextRequest, NextResponse } from "next/server";
import { createSbServer } from "@/lib/supabaseServer";

async function assertStaff(sb: ReturnType<typeof createSbServer>, userId: string) {
  const { data: me } = await sb
    .from("staff_users")
    .select("is_staff")
    .eq("user_id", userId)
    .maybeSingle();
  return !!me?.is_staff;
}

export async function GET(req: NextRequest) {
  const supabase = createSbServer();
  const { data: { user } } = await supabase.auth.getUser();
  
  if (!user) {
    return NextResponse.json({ error: "Non authentifié." }, { status: 401 });
  }
  
  const isStaff = await assertStaff(supabase, user.id);
  if (!isStaff) {
    return NextResponse.json({ error: "Accès réservé au staff." }, { status: 403 });
  }

  const { searchParams } = new URL(req.url);
  
  // Paramètres de recherche et filtres
  const q = searchParams.get('q') || '';
  const structure = searchParams.get('structure') || '';
  const typeDeContrat = searchParams.get('type_de_contrat') || '';
  const processed = searchParams.get('processed') || '';
  const transferDone = searchParams.get('transfer_done') || '';
  const aemStatus = searchParams.get('aem_status') || '';
  const periodFrom = searchParams.get('period_from') || '';
  const periodTo = searchParams.get('period_to') || '';
  const sort = searchParams.get('sort') || 'period_start';
  const order = searchParams.get('order') || 'desc';
  const limit = parseInt(searchParams.get('limit') || '50');
  const offset = parseInt(searchParams.get('offset') || '0');

  console.log('[staff/payslips/search] Filters:', { q, structure, typeDeContrat, processed, transferDone, aemStatus, periodFrom, periodTo, sort, order, limit, offset });
  console.log('[staff/payslips/search] typeDeContrat truthy check:', !!typeDeContrat, 'length:', typeDeContrat?.length);

  try {
    // Construction de la requête avec jointure
    let query = supabase
      .from("payslips")
      .select(
        `id, contract_id, period_start, period_end, period_month, pay_number, pay_date,
        gross_amount, net_amount, net_after_withholding, employer_cost,
        processed, aem_status, transfer_done, organization_id, storage_path, created_at,
        cddu_contracts!contract_id(
          id, contract_number, employee_name, employee_id, structure, type_de_contrat, org_id,
          salaries!employee_id(salarie, nom, prenom),
          organizations!org_id(organization_details(code_employeur))
        )`,
        { count: "exact" }
      );

    // Filtre de recherche textuelle (n° contrat, nom salarié)
    if (q) {
      // Nous devons filtrer côté serveur sur les données de la jointure
      // Supabase ne permet pas de filtrer directement sur les jointures dans le SELECT
      // On va d'abord récupérer tous les contrats qui matchent, puis filter les payslips
      const { data: matchingContracts } = await supabase
        .from("cddu_contracts")
        .select("id")
        .or(`contract_number.ilike.%${q}%,employee_name.ilike.%${q}%`);
      
      if (matchingContracts && matchingContracts.length > 0) {
        const contractIds = matchingContracts.map(c => c.id);
        query = query.in('contract_id', contractIds);
      } else {
        // Aucun contrat ne correspond, retourner un résultat vide
        return NextResponse.json({ rows: [], count: 0 });
      }
    }

    // Filtre par structure (via contrat)
    if (structure) {
      const { data: matchingContracts, error: structureError } = await supabase
        .from("cddu_contracts")
        .select("id")
        .eq("structure", structure);
      
      if (structureError) {
        console.error('[staff/payslips/search] Structure filter error:', structureError);
        return NextResponse.json({ error: "Erreur lors du filtre par structure" }, { status: 500 });
      }
      
      console.log('[staff/payslips/search] Matching contracts for structure:', matchingContracts?.length || 0);
      
      if (matchingContracts && matchingContracts.length > 0) {
        const contractIds = matchingContracts.map(c => c.id);
        
        // Si trop de contrats (>400), on va récupérer toutes les payslips et filtrer côté serveur
        if (contractIds.length > 400) {
          console.log('[staff/payslips/search] Too many contracts, switching to server-side filtering');
          
          // Récupérer toutes les payslips pour la période
          let allQuery = supabase
            .from("payslips")
            .select(
              `id, contract_id, period_start, period_end, period_month, pay_number, pay_date,
              gross_amount, net_amount, net_after_withholding, employer_cost,
              processed, aem_status, transfer_done, organization_id, storage_path, created_at,
              cddu_contracts!contract_id(
                id, contract_number, employee_name, employee_id, structure, type_de_contrat, org_id,
                salaries!employee_id(salarie, nom, prenom),
                organizations!org_id(organization_details(code_employeur))
              )`,
              { count: "exact" }
            );
          
          // Filtres de période
          if (periodFrom) {
            allQuery = allQuery.gte('period_start', periodFrom);
          }
          if (periodTo) {
            allQuery = allQuery.lte('period_start', periodTo);
          }
          
          // Filtres additionnels
          if (processed !== '') {
            allQuery = allQuery.eq('processed', processed === 'true');
          }
          if (transferDone !== '') {
            allQuery = allQuery.eq('transfer_done', transferDone === 'true');
          }
          if (aemStatus) {
            allQuery = allQuery.eq('aem_status', aemStatus);
          }
          
          // Limiter à 10000 pour ne pas surcharger
          allQuery = allQuery.limit(10000);
          
          const { data: allPayslips, error: allError } = await allQuery;
          
          if (allError) {
            console.error('[staff/payslips/search] Error fetching payslips:', allError);
            return NextResponse.json({ error: allError.message }, { status: 500 });
          }
          
          // Filtrer côté serveur par contract_id
          const contractIdsSet = new Set(contractIds);
          let filteredPayslips = (allPayslips || []).filter(p => contractIdsSet.has(p.contract_id));
          
          console.log('[staff/payslips/search] Filtered to', filteredPayslips.length, 'payslips');
          
          // Tri côté serveur
          const ascending = order === 'asc';
          filteredPayslips.sort((a: any, b: any) => {
            let valueA: any, valueB: any;
            
            if (sort === 'employee_name') {
              valueA = a.cddu_contracts?.salaries?.nom || a.cddu_contracts?.employee_name || '';
              valueB = b.cddu_contracts?.salaries?.nom || b.cddu_contracts?.employee_name || '';
            } else if (sort === 'contract_number') {
              valueA = a.cddu_contracts?.contract_number || '';
              valueB = b.cddu_contracts?.contract_number || '';
            } else if (sort === 'structure') {
              valueA = a.cddu_contracts?.structure || '';
              valueB = b.cddu_contracts?.structure || '';
            } else {
              valueA = a[sort];
              valueB = b[sort];
            }
            
            if (typeof valueA === 'string') valueA = valueA.toLowerCase();
            if (typeof valueB === 'string') valueB = valueB.toLowerCase();
            
            if (valueA < valueB) return ascending ? -1 : 1;
            if (valueA > valueB) return ascending ? 1 : -1;
            return 0;
          });
          
          // Pagination
          const paginatedPayslips = filteredPayslips.slice(offset, offset + limit);
          
          return NextResponse.json({
            rows: paginatedPayslips,
            count: filteredPayslips.length
          });
        } else {
          // Assez peu de contrats, on peut utiliser .in()
          query = query.in('contract_id', contractIds);
        }
      } else {
        console.log('[staff/payslips/search] No contracts found for structure, returning empty');
        return NextResponse.json({ rows: [], count: 0 });
      }
    }

    // Filtre par type de contrat (CDDU vs RG)
    // Au lieu de récupérer les IDs de contrats (limité à 1000), on récupère toutes les payslips
    // et on filtre côté serveur par le type_de_contrat de la relation
    if (typeDeContrat) {
      console.log('[staff/payslips/search] Filtering by type:', typeDeContrat);
      
      // Récupérer toutes les payslips avec leurs contrats pour la période
      let allQuery = supabase
        .from("payslips")
        .select(
          `id, contract_id, period_start, period_end, period_month, pay_number, pay_date,
          gross_amount, net_amount, net_after_withholding, employer_cost,
          processed, aem_status, transfer_done, organization_id, created_at,
          cddu_contracts!contract_id(
            id, contract_number, employee_name, employee_id, structure, type_de_contrat, org_id,
            salaries!employee_id(salarie, nom, prenom)
          )`,
          { count: "exact" }
        );
      
      // Appliquer les filtres de période en amont
      if (periodFrom) {
        allQuery = allQuery.gte('period_start', periodFrom);
      }
      if (periodTo) {
        allQuery = allQuery.lte('period_start', periodTo);
      }
      
      // Limiter à 10000 pour ne pas surcharger
      allQuery = allQuery.limit(10000);
      
      const { data: allPayslips, error: allError } = await allQuery;
      
      if (allError) {
        console.error('[staff/payslips/search] Error fetching all payslips:', allError);
        return NextResponse.json({ error: allError.message }, { status: 500 });
      }
      
      console.log('[staff/payslips/search] Retrieved', allPayslips?.length, 'total payslips from DB');
      
      // Filtrer côté serveur par type de contrat
      let filteredPayslips = (allPayslips || []).filter(p => {
        const contract = Array.isArray(p.cddu_contracts) ? p.cddu_contracts[0] : p.cddu_contracts;
        if (!contract) return false;
        
        if (typeDeContrat === "RG") {
          return contract.type_de_contrat === "CDD de droit commun" || contract.type_de_contrat === "CDI";
        } else {
          return contract.type_de_contrat === typeDeContrat;
        }
      });
      
      console.log('[staff/payslips/search] Filtered to', filteredPayslips.length, 'payslips after contract type filter');
      
      // Appliquer les autres filtres manuellement
      let finalPayslips = filteredPayslips;
      
      if (processed !== '') {
        finalPayslips = finalPayslips.filter(p => p.processed === (processed === 'true'));
      }
      if (transferDone !== '') {
        finalPayslips = finalPayslips.filter(p => p.transfer_done === (transferDone === 'true'));
        
        // Si on filtre sur "virement en attente", ne garder que les clients Odentas
        if (transferDone === 'false') {
          finalPayslips = finalPayslips.filter((p: any) => {
            const contract = Array.isArray(p.cddu_contracts) ? p.cddu_contracts[0] : p.cddu_contracts;
            const org = contract?.organizations || (Array.isArray(p.cddu_contracts?.organizations) ? p.cddu_contracts.organizations[0] : p.cddu_contracts?.organizations);
            const orgDetails = org?.organization_details || (Array.isArray(org?.organization_details) ? org.organization_details[0] : org?.organization_details);
            return orgDetails?.virements_salaires?.toLowerCase() === 'odentas';
          });
        }
      }
      if (aemStatus) {
        finalPayslips = finalPayslips.filter(p => p.aem_status === aemStatus);
      }
      
      // Tri côté serveur
      const ascending = order === 'asc';
      finalPayslips.sort((a, b) => {
        let valueA: any, valueB: any;
        
        // cddu_contracts est un objet, pas un tableau dans ce contexte
        const contractA = Array.isArray(a.cddu_contracts) ? a.cddu_contracts[0] : a.cddu_contracts;
        const contractB = Array.isArray(b.cddu_contracts) ? b.cddu_contracts[0] : b.cddu_contracts;
        
        if (sort === 'employee_name') {
          valueA = contractA?.employee_name || '';
          valueB = contractB?.employee_name || '';
        } else if (sort === 'contract_number') {
          valueA = contractA?.contract_number || '';
          valueB = contractB?.contract_number || '';
        } else if (sort === 'structure') {
          valueA = contractA?.structure || '';
          valueB = contractB?.structure || '';
        } else {
          valueA = (a as any)[sort];
          valueB = (b as any)[sort];
        }
        
        if (typeof valueA === 'string') valueA = valueA.toLowerCase();
        if (typeof valueB === 'string') valueB = valueB.toLowerCase();
        
        if (valueA < valueB) return ascending ? -1 : 1;
        if (valueA > valueB) return ascending ? 1 : -1;
        return 0;
      });
      
      // Pagination
      const paginatedPayslips = finalPayslips.slice(offset, offset + limit);
      
      return NextResponse.json({
        rows: paginatedPayslips,
        count: finalPayslips.length
      });
    }

    // Filtre par état de traitement
    if (processed !== '') {
      query = query.eq('processed', processed === 'true');
    }

    // Filtre par état de virement
    if (transferDone !== '') {
      query = query.eq('transfer_done', transferDone === 'true');
      
      // Si on filtre sur "virement en attente", ne garder que les clients avec virements_salaires = "Odentas"
      if (transferDone === 'false') {
        const { data: odentasOrgs } = await supabase
          .from('organization_details')
          .select('org_id')
          .ilike('virements_salaires', 'odentas');
        
        if (odentasOrgs && odentasOrgs.length > 0) {
          const odentasOrgIds = odentasOrgs.map(o => o.org_id).filter(Boolean);
          query = query.in('organization_id', odentasOrgIds);
        } else {
          // Aucune org Odentas, retourner vide
          return NextResponse.json({ rows: [], count: 0 });
        }
      }
    }

    // Filtre par AEM
    if (aemStatus) {
      query = query.eq('aem_status', aemStatus);
    }

    // Filtre par période
    if (periodFrom) {
      query = query.gte('period_start', periodFrom);
    }
    if (periodTo) {
      query = query.lte('period_start', periodTo);
    }

    // Tri
    const ascending = order === 'asc';
    
    // Pour le tri par des champs de la jointure, on devra trier côté client
    // Pour l'instant, on trie uniquement sur les champs de payslips
    const sortableFields = ['period_start', 'period_end', 'pay_number', 'pay_date', 'gross_amount', 'net_amount', 'created_at'];
    if (sortableFields.includes(sort)) {
      query = query.order(sort, { ascending });
    } else {
      // Fallback sur period_start
      query = query.order('period_start', { ascending });
    }

    // Pagination
    query = query.range(offset, offset + limit - 1);

    console.log('[staff/payslips/search] Executing query...');
    const { data: payslips, error, count } = await query;

    if (error) {
      console.error('[staff/payslips/search] Supabase query error:', error);
      console.error('[staff/payslips/search] Error details:', { message: error.message, details: error.details, hint: error.hint, code: error.code });
      return NextResponse.json({ error: error.message }, { status: 500 });
    }

    // Si le tri est sur des champs de la jointure, on trie côté serveur
    let sortedPayslips = payslips || [];
    if (sort === 'contract_number' || sort === 'employee_name' || sort === 'structure') {
      sortedPayslips = [...sortedPayslips].sort((a: any, b: any) => {
        let valueA: any;
        let valueB: any;

        if (sort === 'contract_number') {
          valueA = a.cddu_contracts?.contract_number || '';
          valueB = b.cddu_contracts?.contract_number || '';
        } else if (sort === 'employee_name') {
          valueA = a.cddu_contracts?.salaries?.nom || a.cddu_contracts?.employee_name || '';
          valueB = b.cddu_contracts?.salaries?.nom || b.cddu_contracts?.employee_name || '';
        } else if (sort === 'structure') {
          valueA = a.cddu_contracts?.structure || '';
          valueB = b.cddu_contracts?.structure || '';
        }

        if (typeof valueA === 'string') valueA = valueA.toLowerCase();
        if (typeof valueB === 'string') valueB = valueB.toLowerCase();

        if (valueA < valueB) return ascending ? -1 : 1;
        if (valueA > valueB) return ascending ? 1 : -1;
        return 0;
      });
    }

    console.log(`[staff/payslips/search] Found ${sortedPayslips.length} payslips (total: ${count})`);

    return NextResponse.json({
      rows: sortedPayslips,
      count: count ?? sortedPayslips.length
    });

  } catch (error: any) {
    console.error('[staff/payslips/search] Unexpected error:', error);
    console.error('[staff/payslips/search] Error details:', { message: error?.message, stack: error?.stack });
    return NextResponse.json({ error: error?.message || "Erreur lors de la recherche" }, { status: 500 });
  }
}
