import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextRequest, NextResponse } from "next/server";
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

export const dynamic = "force-dynamic";

const s3Client = new S3Client({
  region: process.env.AWS_REGION || "eu-west-3",
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  },
});

// Fonction de polling pour attendre la génération du PDF
async function pollDocumentStatus(
  documentUrl: string,
  apiKey: string,
  maxAttempts = 15,
  intervalMs = 2000
): Promise<{ status: string; download_url?: string }> {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    console.log(`[NAA Regenerate] Poll attempt ${attempt}/${maxAttempts}`);
    
    const res = await fetch(documentUrl, {
      headers: { Authorization: `Bearer ${apiKey}` }
    });
    
    if (!res.ok) {
      throw new Error(`Failed to poll document status: ${res.statusText}`);
    }
    
    const data = await res.json();
    const status = data.document?.status;
    
    console.log(`[NAA Regenerate] Poll attempt ${attempt}/${maxAttempts}, status: ${status}`);
    
    if (status === "success" && data.document?.download_url) {
      return { status, download_url: data.document.download_url };
    }
    
    if (status === "error" || status === "failure") {
      throw new Error(`PDF generation failed with status: ${status}`);
    }
    
    if (attempt < maxAttempts) {
      await new Promise(resolve => setTimeout(resolve, intervalMs));
    }
  }
  
  return { status: "timeout" };
}

export async function POST(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const cookieStore = cookies();
    const supabase = createRouteHandlerClient({ cookies: () => cookieStore });

    // Vérifier l'authentification staff
    const { data: { user } } = await supabase.auth.getUser();
    if (!user) {
      return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
    }

    const { data: staffUser } = await supabase
      .from("staff_users")
      .select("user_id")
      .eq("user_id", user.id)
      .single();

    if (!staffUser) {
      return NextResponse.json({ error: "Accès non autorisé" }, { status: 403 });
    }

    console.log(`[NAA Regenerate] Starting regeneration for NAA ID: ${params.id}`);

    // Lire le body (optionnel) pour récupérer les factures explicitement incluses
    let includedInvoiceIds: string[] = [];
    try {
      const reqBody = await request.json();
      includedInvoiceIds = Array.isArray(reqBody?.included_invoices) ? reqBody.included_invoices : [];
    } catch (e) {
      // pas de body
      includedInvoiceIds = [];
    }

    // Si des invoice IDs sont fournis, précharger ces factures
    let includedInvoicesMap: Record<string, any> = {};
    if (includedInvoiceIds && includedInvoiceIds.length > 0) {
      const { data: includedInvoices } = await supabase
        .from('invoices')
        .select('id, amount_ht, org_id, created_at, period_label')
        .in('id', includedInvoiceIds as string[]);

      if (includedInvoices && includedInvoices.length > 0) {
        for (const inv of includedInvoices) {
          includedInvoicesMap[inv.id] = inv;
        }
      }
      console.log(`[NAA Regenerate] ${Object.keys(includedInvoicesMap).length} included invoices preloaded`);
    }

    // Récupérer le document NAA avec l'apporteur
    const { data: naaDoc, error: naaError } = await supabase
      .from("naa_documents")
      .select(`
        *,
        referrers (*)
      `)
      .eq("id", params.id)
      .single();

    if (naaError || !naaDoc) {
      return NextResponse.json({ error: "NAA non trouvée" }, { status: 404 });
    }

    // Récupérer les prestations actuelles
    const { data: prestations } = await supabase
      .from("naa_prestations")
      .select("*")
      .eq("naa_id", params.id)
      .order("created_at");

    const referrer = Array.isArray(naaDoc.referrers) ? naaDoc.referrers[0] : naaDoc.referrers;

    // ===== RECALCUL COMPLET DES COMMISSIONS =====
    console.log("[NAA Regenerate] Recalculating commissions from scratch...");
    
    // Extraire le mois et l'année de la période (format : "Janvier 2025")
    const periodeParts = naaDoc.periode.split(" ");
    const monthNames = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"];
    const periodMonth = monthNames.indexOf(periodeParts[0]) + 1;
    const periodYear = parseInt(periodeParts[1]);
    const month = periodMonth.toString().padStart(2, '0');
    
    // Calcul du mois d'émission (mois suivant)
    let emissionMonth = periodMonth + 1;
    let emissionYear = periodYear;
    
    if (emissionMonth > 12) {
      emissionMonth = 1;
      emissionYear += 1;
    }
    
    const emissionMonthStr = emissionMonth.toString().padStart(2, '0');
    const emissionStartDate = `${emissionYear}-${emissionMonthStr}-01`;
    const emissionEndDate = `${emissionYear}-${emissionMonthStr}-20`;

    // Récupérer la liste actuelle des clients apportés (peut avoir changé)
    const { data: referredClients, error: clientsError } = await supabase
      .from("organization_details")
      .select(`
        org_id,
        referrer_code,
        commission_rate,
        code_employeur,
        organizations!organization_details_org_id_fkey (
          id,
          name
        )
      `)
      .eq("is_referred", true)
      .eq("referrer_code", naaDoc.referrer_code);

    if (clientsError) {
      console.error("[NAA Regenerate] Erreur récupération clients apportés:", clientsError);
      return NextResponse.json(
        { error: "Erreur lors de la récupération des clients" },
        { status: 500 }
      );
    }

    console.log(`[NAA Regenerate] Trouvé ${referredClients?.length || 0} clients apportés actuellement`);

    // Recalculer les line items pour chaque client apporté
    const newLineItems = [];
    let totalCommission = 0;

    for (const client of referredClients || []) {
      const org = Array.isArray(client.organizations) ? client.organizations[0] : client.organizations;
      const clientCode = client.code_employeur;
      const clientName = org?.name || 'N/A';
      
      console.log(`[NAA Regenerate] Recherche facture pour client ${clientName} (${clientCode})`);

      // Si l'utilisateur a fourni des invoices incluses, vérifier s'il y en a pour ce client
      let invoice: any | null = null;
      if (includedInvoiceIds && includedInvoiceIds.length > 0) {
        const matching = Object.values(includedInvoicesMap).filter((inv: any) => String(inv.org_id) === String(client.org_id));
        if (matching && matching.length > 0) {
          // prendre la plus récente
          invoice = matching.sort((a: any, b: any) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0];
          console.log(`[NAA Regenerate]   ✅ Utilisation d'une facture explicitement incluse: ${invoice.id}`);
        }
      }

      // Stratégie 1 : Recherche exacte par period_label (si pas de facture fournie)
      if (!invoice) {
        invoice = await supabase
          .from("invoices")
          .select("id, amount_ht, created_at, period_label")
          .eq("org_id", client.org_id)
          .eq("period_label", naaDoc.periode)
          .order("created_at", { ascending: false })
          .limit(1)
          .maybeSingle()
          .then(res => res.data);
      }
      
      // Stratégie 2 : Si pas trouvé, chercher par date de création
      if (!invoice) {
        invoice = await supabase
          .from("invoices")
          .select("id, amount_ht, created_at, period_label")
          .eq("org_id", client.org_id)
          .gte("created_at", emissionStartDate)
          .lte("created_at", emissionEndDate)
          .order("created_at", { ascending: false })
          .limit(1)
          .maybeSingle()
          .then(res => res.data);
      }

      // Stratégie 3 : Chercher dans une plage élargie
      if (!invoice) {
        const { data: invoices } = await supabase
          .from("invoices")
          .select("id, amount_ht, created_at, period_label")
          .eq("org_id", client.org_id)
          .gte("created_at", `${periodYear}-${month}-01`)
          .lte("created_at", `${emissionYear}-${emissionMonthStr}-31`)
          .order("created_at", { ascending: false });
        
        if (invoices && invoices.length > 0) {
          invoice = invoices[0];
        }
      }

      if (invoice && invoice.amount_ht > 0) {
        const caHT = parseFloat(invoice.amount_ht);
        const commissionRate = client.commission_rate || 0;
        const commission = caHT * commissionRate;
        totalCommission += commission;

        console.log(`[NAA Regenerate]   ✅ Commission: ${caHT}€ × ${(commissionRate * 100).toFixed(2)}% = ${commission.toFixed(2)}€`);

        newLineItems.push({
          naa_id: params.id,
          organization_id: client.org_id,
          client_name: clientName,
          client_code: clientCode,
          invoice_id: invoice.id || null,
          commission_rate: commissionRate,
          ca_ht: caHT,
          commission: commission
        });
      } else {
        console.log(`[NAA Regenerate]   ⚠️ Aucune facture trouvée ou montant HT = 0`);
      }
    }

    // Supprimer les anciens line items et insérer les nouveaux
    await supabase
      .from("naa_line_items")
      .delete()
      .eq("naa_id", params.id);

    if (newLineItems.length > 0) {
      await supabase
        .from("naa_line_items")
        .insert(newLineItems);
    }

    // Recalculer les totaux
    const nbreClients = newLineItems.length;
    const nbrePrestations = (prestations || []).length;
    const totalFacture = totalCommission - (naaDoc.deposit || 0) + (naaDoc.solde_compte_apporteur || 0);
    
    console.log(`[NAA Regenerate] Totaux recalculés:`);
    console.log(`  - Nombre de clients: ${nbreClients}`);
    console.log(`  - Nombre de prestations: ${nbrePrestations}`);
    console.log(`  - Total commission: ${totalCommission.toFixed(2)}€`);
    console.log(`  - Total facture: ${totalFacture.toFixed(2)}€`);

    // Mettre à jour le document NAA avec les nouveaux totaux
    await supabase
      .from("naa_documents")
      .update({
        total_commission: totalCommission,
        total_facture: totalFacture,
        nbre_clients: nbreClients,
        nbre_prestations: nbrePrestations,
        updated_at: new Date().toISOString()
      })
      .eq("id", params.id);

    // Trier les line items par ordre alphabétique de code client
    const sortedLineItems = (newLineItems || [])
      .map((item: any) => ({
        id: item.client_code || '',
        client: item.client_name || '',
        code: item.client_code || '',
        comactuelle: item.commission_rate || 0,
        caht: item.ca_ht || 0,
        commission: item.commission || 0
      }))
      .sort((a: any, b: any) => {
        const codeA = a.code.toLowerCase();
        const codeB = b.code.toLowerCase();
        return codeA.localeCompare(codeB);
      });    // Trier les prestations par ordre alphabétique du code client
    const sortedPrestations = (prestations || [])
      .map(p => ({
        client: p.client_name,
        code: p.client_code,
        type_prestation: p.type_prestation,
        quantite: p.quantite,
        tarif: p.tarif,
        total: p.total
      }))
      .sort((a, b) => {
        const codeA = (a.code || "").toUpperCase();
        const codeB = (b.code || "").toUpperCase();
        return codeA.localeCompare(codeB);
      });

    // Préparer le payload pour PDFMonkey avec les totaux recalculés
    const pdfMonkeyPayload = {
      apporteur_address: referrer?.address || "",
      apporteur_cp: referrer?.postal_code || "",
      apporteur_city: referrer?.city || "",
      apporteur_code: referrer?.code || naaDoc.referrer_code,
      apporteur_name: referrer?.name || "",
      apporteur_contact: referrer?.contact_name || "",
      callsheet_date: new Date(naaDoc.callsheet_date).toLocaleDateString("fr-FR"),
      limit_date: naaDoc.limit_date ? new Date(naaDoc.limit_date).toLocaleDateString("fr-FR") : "",
      callsheet_number: naaDoc.naa_number,
      periode: naaDoc.periode,
      total_commission: totalCommission,
      solde_compte_apporteur: naaDoc.solde_compte_apporteur || 0,
      total_facture: totalFacture,
      deposit: naaDoc.deposit || 0,
      nbre_clients: nbreClients,
      nbre_prestations: nbrePrestations,
      transfer_reference: naaDoc.transfer_reference || "",
      logo_odentas: "",
      lineItems: sortedLineItems,
      prestations: sortedPrestations
    };

    console.log("[NAA Regenerate] Calling PDFMonkey API...");
    console.log("[NAA Regenerate] Payload lineItems:", JSON.stringify(sortedLineItems, null, 2));

    const pdfMonkeyApiKey = process.env.PDFMONKEY_API_KEY;
    const pdfMonkeyUrl = "https://api.pdfmonkey.io/api/v1/documents";
    const templateId = process.env.PDFMONKEY_NAA_TEMPLATE_ID || "422DA8A6-69E1-4798-B4A3-DF75D892BF2D";

    const pdfMonkeyRes = await fetch(pdfMonkeyUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${pdfMonkeyApiKey}`,
      },
      body: JSON.stringify({
        document: {
          document_template_id: templateId,
          status: "pending",
          payload: pdfMonkeyPayload,
        },
      }),
    });

    if (!pdfMonkeyRes.ok) {
      const errorText = await pdfMonkeyRes.text();
      console.error("[NAA Regenerate] PDFMonkey API error:", errorText);
      return NextResponse.json(
        { error: "Erreur lors de l'appel à PDFMonkey" },
        { status: 500 }
      );
    }

    const pdfMonkeyData = await pdfMonkeyRes.json();
    console.log("[NAA Regenerate] PDFMonkey response:", pdfMonkeyData);

    const documentId = pdfMonkeyData.document?.id;
    if (!documentId) {
      return NextResponse.json({ error: "No document ID returned from PDFMonkey" }, { status: 500 });
    }

    const documentUrl = `${pdfMonkeyUrl}/${documentId}`;
    console.log("[NAA Regenerate] Polling document status...");
    
    const { status, download_url } = await pollDocumentStatus(documentUrl, pdfMonkeyApiKey!, 15, 2000);
    
    if (status !== "success" || !download_url) {
      return NextResponse.json({ error: "PDF generation failed or timed out" }, { status: 500 });
    }

    // Télécharger le PDF
    console.log("[NAA Regenerate] Downloading PDF...");
    const pdfRes = await fetch(download_url);
    if (!pdfRes.ok) {
      return NextResponse.json({ error: "Failed to download PDF" }, { status: 500 });
    }
    const pdfBuffer = Buffer.from(await pdfRes.arrayBuffer());
    console.log("[NAA Regenerate] PDF downloaded, size:", pdfBuffer.length, "bytes");

    // Uploader sur S3
    console.log("[NAA Regenerate] Uploading to S3...");
    const bucketName = process.env.AWS_S3_BUCKET_NAME || "odentas-docs";
    const s3Key = `naa/${naaDoc.naa_number}.pdf`;
    
    const uploadCommand = new PutObjectCommand({
      Bucket: bucketName,
      Key: s3Key,
      Body: pdfBuffer,
      ContentType: "application/pdf",
    });

    await s3Client.send(uploadCommand);
    console.log("[NAA Regenerate] S3 upload successful");

    const s3Url = `https://${bucketName}.s3.${process.env.AWS_REGION || "eu-west-3"}.amazonaws.com/${s3Key}`;

    // Générer une URL présignée
    const getObjectCommand = new GetObjectCommand({
      Bucket: bucketName,
      Key: s3Key,
    });
    const presignedUrl = await getSignedUrl(s3Client, getObjectCommand, { expiresIn: 3600 });

    // Mettre à jour le document NAA avec l'URL du PDF (les totaux ont déjà été mis à jour plus haut)
    await supabase
      .from("naa_documents")
      .update({
        pdf_url: s3Url,
        s3_key: s3Key,
        status: "sent"
      })
      .eq("id", params.id);

    console.log("[NAA Regenerate] ✅ NAA regeneration completed successfully");
    
    return NextResponse.json({
      success: true,
      pdf_url: s3Url,
      presigned_url: presignedUrl
    });

  } catch (error: any) {
    console.error("[NAA Regenerate] ❌ Error:", error);
    return NextResponse.json(
      { error: error.message || "Erreur serveur" },
      { status: 500 }
    );
  }
}
