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 i = 0; i < maxAttempts; i++) {
    await new Promise((resolve) => setTimeout(resolve, intervalMs));
    const res = await fetch(documentUrl, {
      headers: { Authorization: `Bearer ${apiKey}` },
    });
    if (!res.ok) {
      throw new Error(`Poll failed: ${res.statusText}`);
    }
    const data = await res.json();
    const doc = data.document || data;
    const status = doc.status;
    
    console.log(`[NAA] Poll attempt ${i + 1}/${maxAttempts}, status: ${status}`);
    
    if (status === "success") {
      return { status, download_url: doc.download_url };
    }
    if (status === "failure") {
      throw new Error("PDFMonkey document generation failed");
    }
  }
  throw new Error("PDFMonkey polling timed out");
}

type Prestation = {
  client: string;
  code: string;
  type_prestation: string;
  quantite: number;
  tarif: number;
  total: number;
};

export async function POST(req: NextRequest) {
  try {
    const supabase = createRouteHandlerClient({ cookies });

    const { data: { session } } = await supabase.auth.getSession();
    if (!session) {
      return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
    }

    // Vérifier que l'utilisateur est staff
    const { data: staffUser } = await supabase
      .from("staff_users")
      .select("is_staff")
      .eq("user_id", session.user.id)
      .single();

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

    const body = await req.json();
    const {
      referrer_code,
      periode,
      callsheet_date,
      limit_date,
      transfer_reference,
      solde_compte_apporteur = 0,
      deposit = 0,
      prestations = []
    }: {
      referrer_code: string;
      periode: string;
      callsheet_date: string;
      limit_date?: string;
      transfer_reference?: string;
      solde_compte_apporteur: number;
      deposit: number;
      prestations: Prestation[];
    } = body;

    // Validation
    if (!referrer_code || !periode || !callsheet_date) {
      return NextResponse.json(
        { error: "Champs obligatoires manquants" },
        { status: 400 }
      );
    }

    // Récupérer les infos de l'apporteur
    const { data: referrer, error: referrerError } = await supabase
      .from("referrers")
      .select("*")
      .eq("code", referrer_code)
      .single();

    if (referrerError || !referrer) {
      return NextResponse.json(
        { error: "Apporteur non trouvé" },
        { status: 404 }
      );
    }

    // Récupérer les clients apportés par cet apporteur avec les factures de la période
    // Format de période attendu : "Février 2025" -> on extrait le mois et l'année
    const [monthName, year] = periode.split(" ");
    const monthMap: { [key: string]: string } = {
      "Janvier": "01", "Février": "02", "Mars": "03", "Avril": "04",
      "Mai": "05", "Juin": "06", "Juillet": "07", "Août": "08",
      "Septembre": "09", "Octobre": "10", "Novembre": "11", "Décembre": "12"
    };
    const month = monthMap[monthName];

    if (!month || !year) {
      return NextResponse.json(
        { error: "Format de période invalide (attendu: 'Mois YYYY')" },
        { status: 400 }
      );
    }

    // Calculer le mois suivant (pour la date d'émission des factures)
    const periodMonth = parseInt(month);
    const periodYear = parseInt(year);
    let emissionMonth = periodMonth + 1;
    let emissionYear = periodYear;
    
    if (emissionMonth > 12) {
      emissionMonth = 1;
      emissionYear += 1;
    }
    
    const emissionMonthStr = emissionMonth.toString().padStart(2, '0');
    
    // Date de début et fin du mois d'émission (1er au 20 du mois suivant)
    const emissionStartDate = `${emissionYear}-${emissionMonthStr}-01`;
    const emissionEndDate = `${emissionYear}-${emissionMonthStr}-20`;

    // Récupérer les clients apportés
    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", referrer_code);

    if (clientsError) {
      console.error("[NAA] 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] Trouvé ${referredClients?.length || 0} clients apportés par ${referrer_code}`);
    if (referredClients && referredClients.length > 0) {
      console.log("[NAA] Clients:", referredClients.map(c => {
        const org = Array.isArray(c.organizations) ? c.organizations[0] : c.organizations;
        return {
          name: org?.name || 'N/A',
          code: c.code_employeur,
          commission_rate: c.commission_rate
        };
      }));
    }

    // Pour chaque client, récupérer les factures du mois concerné
    const lineItems = [];
    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] Recherche facture pour client ${clientName} (${clientCode}), période: ${periode}`);
      console.log(`[NAA]   org_id utilisé pour la recherche: ${client.org_id}`);

      // Stratégie 1 : Recherche exacte par period_label
      let invoice = await supabase
        .from("invoices")
        .select("amount_ht, created_at, period_label")
        .eq("org_id", client.org_id)
        .eq("period_label", periode)
        .order("created_at", { ascending: false })
        .limit(1)
        .maybeSingle()
        .then(res => res.data);
      
      console.log(`[NAA]   Stratégie 1 (period_label="${periode}"): ${invoice ? `Trouvé ${invoice.amount_ht}€` : 'Rien trouvé'}`);

      // Stratégie 2 : Si pas trouvé, chercher par date de création (factures émises début du mois suivant)
      if (!invoice) {
        invoice = await supabase
          .from("invoices")
          .select("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);
        
        console.log(`[NAA]   Stratégie 2 (dates ${emissionStartDate} à ${emissionEndDate}): ${invoice ? `Trouvé ${invoice.amount_ht}€` : 'Rien trouvé'}`);
      }

      // Stratégie 3 : Chercher dans une plage élargie si toujours rien
      if (!invoice) {
        // Chercher toutes les factures du client dans une plage de ±2 mois
        const { data: invoices } = await supabase
          .from("invoices")
          .select("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 });
        
        console.log(`[NAA]   Stratégie 3 (plage élargie): ${invoices?.length || 0} facture(s) trouvée(s)`);
        
        if (invoices && invoices.length > 0) {
          invoice = invoices[0]; // Prendre la plus récente
          console.log(`[NAA]   Utilisation de la facture la plus récente: ${invoice.amount_ht}€ (${invoice.period_label})`);
        }
      }

      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]   ✅ Commission calculée: ${caHT}€ × ${(commissionRate * 100).toFixed(2)}% = ${commission.toFixed(2)}€`);

        lineItems.push({
          id: clientCode || "UNKNOWN",
          client: org.name,
          code: clientCode,
          comactuelle: commissionRate,
          caht: caHT,
          commission: commission
        });
      } else {
        console.log(`[NAA]   ⚠️ Aucune facture trouvée ou montant HT = 0`);
      }
    }

    console.log(`[NAA] Total commission calculée: ${totalCommission.toFixed(2)}€`);
    console.log(`[NAA] Nombre de line items: ${lineItems.length}`);

    const nbreClients = lineItems.length;
    const nbrePrestations = prestations.length;
    const totalFacture = totalCommission - deposit + solde_compte_apporteur;

    // Utiliser la référence de virement comme numéro de NAA
    const finalNAANumber = transfer_reference || `NAA-${Date.now()}`;

    // Créer le document NAA dans la base
    const { data: naaDoc, error: naaError } = await supabase
      .from("naa_documents")
      .insert({
        naa_number: finalNAANumber,
        referrer_id: referrer.id,
        referrer_code: referrer_code,
        periode,
        callsheet_date,
        limit_date: limit_date || null,
        total_commission: totalCommission,
        solde_compte_apporteur,
        total_facture: totalFacture,
        deposit,
        nbre_clients: nbreClients,
        nbre_prestations: nbrePrestations,
        transfer_reference: transfer_reference || null,
        status: "draft",
        created_by: session.user.id
      })
      .select()
      .single();

    if (naaError) {
      console.error("Erreur création NAA:", naaError);
      return NextResponse.json(
        { error: "Erreur lors de la création de la NAA" },
        { status: 500 }
      );
    }

    // Insérer les line items
    if (lineItems.length > 0) {
      const lineItemsToInsert = lineItems.map(item => {
        const clientData = referredClients?.find(c => {
          const clientCode = c.code_employeur || "";
          return clientCode === item.code;
        });
        
        return {
          naa_id: naaDoc.id,
          organization_id: clientData?.org_id,
          client_name: item.client,
          client_code: item.code,
          commission_rate: item.comactuelle,
          ca_ht: item.caht,
          commission: item.commission
        };
      });

      await supabase.from("naa_line_items").insert(lineItemsToInsert);
    }

    // Insérer les prestations
    if (prestations.length > 0) {
      console.log(`[NAA Generate] Insertion de ${prestations.length} prestations`);
      const prestationsToInsert = prestations.map(p => ({
        naa_id: naaDoc.id,
        client_name: p.client,
        client_code: p.code,
        type_prestation: p.type_prestation,
        quantite: p.quantite,
        tarif: p.tarif,
        total: p.total
      }));

      console.log("[NAA Generate] Prestations à insérer:", JSON.stringify(prestationsToInsert, null, 2));

      const { data: insertedPrestations, error: prestationsError } = await supabase
        .from("naa_prestations")
        .insert(prestationsToInsert)
        .select();

      if (prestationsError) {
        console.error("[NAA Generate] Erreur insertion prestations:", prestationsError);
        return NextResponse.json(
          { error: "Erreur lors de l'insertion des prestations: " + prestationsError.message },
          { status: 500 }
        );
      }

      console.log(`[NAA Generate] ${insertedPrestations?.length || 0} prestations insérées avec succès`);
    } else {
      console.log("[NAA Generate] Aucune prestation à insérer");
    }

    // Trier les lineItems par ordre alphabétique du code client
    const sortedLineItems = [...lineItems].sort((a, b) => {
      const codeA = (a.code || "").toUpperCase();
      const codeB = (b.code || "").toUpperCase();
      return codeA.localeCompare(codeB);
    });

    // Trier les prestations par ordre alphabétique du code client
    const sortedPrestations = [...prestations]
      .map(p => ({
        client: p.client,
        code: p.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 les données pour PDFMonkey
    const pdfMonkeyPayload = {
      apporteur_address: referrer.address,
      apporteur_cp: referrer.postal_code,
      apporteur_city: referrer.city,
      apporteur_code: referrer.code,
      apporteur_name: referrer.name,
      apporteur_contact: referrer.contact_name,
      callsheet_date: new Date(callsheet_date).toLocaleDateString("fr-FR"),
      limit_date: limit_date ? new Date(limit_date).toLocaleDateString("fr-FR") : "",
      callsheet_number: finalNAANumber,
      periode,
      total_commission: totalCommission,
      solde_compte_apporteur,
      total_facture: totalFacture,
      deposit,
      nbre_clients: nbreClients,
      nbre_prestations: nbrePrestations,
      transfer_reference: transfer_reference || "",
      logo_odentas: "",
      lineItems: sortedLineItems,
      prestations: sortedPrestations
    };

    // Envoyer à PDFMonkey pour générer le PDF
    const templateId = process.env.PDFMONKEY_NAA_TEMPLATE_ID || "422DA8A6-69E1-4798-B4A3-DF75D892BF2D";
    const pdfMonkeyUrl = process.env.PDFMONKEY_URL || "https://api.pdfmonkey.io/api/v1/documents";
    const pdfMonkeyApiKey = process.env.PDFMONKEY_API_KEY;

    if (!pdfMonkeyApiKey) {
      console.error("[NAA] Missing PDFMONKEY_API_KEY");
      return NextResponse.json({ error: "Missing PDFMONKEY_API_KEY" }, { status: 500 });
    }

    console.log("[NAA] Calling PDFMonkey API...");
    const pdfMonkeyResponse = await fetch(pdfMonkeyUrl, {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${pdfMonkeyApiKey}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        document: {
          document_template_id: templateId,
          status: "pending",
          payload: pdfMonkeyPayload,
          meta: {
            _filename: `${finalNAANumber}.pdf`
          }
        }
      })
    });

    if (!pdfMonkeyResponse.ok) {
      const errorText = await pdfMonkeyResponse.text();
      console.error("[NAA] PDFMonkey create error:", errorText);
      return NextResponse.json(
        { error: "PDFMonkey API error", details: errorText },
        { status: pdfMonkeyResponse.status }
      );
    }

    const pdfMonkeyData = await pdfMonkeyResponse.json();
    console.log("[NAA] PDFMonkey response:", pdfMonkeyData);
    
    const documentId = pdfMonkeyData.document?.id;
    if (!documentId) {
      console.error("[NAA] No document ID in response");
      return NextResponse.json({ error: "No document ID returned from PDFMonkey" }, { status: 500 });
    }

    // Construct the document URL for polling
    const documentUrl = `${pdfMonkeyUrl}/${documentId}`;
    console.log("[NAA] Document URL for polling:", documentUrl);

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

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

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

    await s3Client.send(uploadCommand);
    console.log("[NAA] 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 valide 1 heure pour afficher le PDF
    console.log("[NAA] Generating presigned URL...");
    const getObjectCommand = new GetObjectCommand({
      Bucket: bucketName,
      Key: s3Key,
    });
    const presignedUrl = await getSignedUrl(s3Client, getObjectCommand, { expiresIn: 3600 });
    console.log("[NAA] Presigned URL generated");

    // Mettre à jour le document NAA avec l'URL du PDF
    console.log("[NAA] Updating NAA document with PDF URL...");
    await supabase
      .from("naa_documents")
      .update({
        pdf_url: s3Url,
        s3_key: s3Key,
        status: "sent"
      })
      .eq("id", naaDoc.id);

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

  } catch (error: any) {
    console.error("[NAA] ❌ Error POST /api/staff/naa/generate:", error);
    return NextResponse.json(
      { error: error.message || "Erreur serveur" },
      { status: 500 }
    );
  }
}
