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

// =============================================================================
// Helper: Poll PDFMonkey document status
// =============================================================================
async function pollDocumentStatus(
  documentUrl: string,
  apiKey: string,
  maxAttempts = 10,
  intervalMs = 3000
): 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;
    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");
}

// =============================================================================
// Helper: Format date as DD/MM/YYYY
// =============================================================================
function formatDateFR(dateString: string | null | undefined): string {
  if (!dateString) return "";
  try {
    const date = new Date(dateString);
    return date.toLocaleDateString("fr-FR", {
      day: "2-digit",
      month: "2-digit",
      year: "numeric",
    });
  } catch {
    return "";
  }
}

// =============================================================================
// Helper: Format amount
// =============================================================================
function formatAmount(amount: string | number | null | undefined): string {
  if (!amount) return "0,00";
  try {
    const num = typeof amount === "string" ? parseFloat(amount) : amount;
    return new Intl.NumberFormat("fr-FR", {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    }).format(num);
  } catch {
    return "0,00";
  }
}

// =============================================================================
// Helper: Format month period as "Mois YYYY"
// =============================================================================
function formatMonthPeriod(periodMonth: string | null | undefined): string {
  if (!periodMonth) return "";
  try {
    const date = new Date(periodMonth);
    return date.toLocaleDateString("fr-FR", {
      month: "long",
      year: "numeric",
    });
  } catch {
    return "";
  }
}

// =============================================================================
// Helper: Slugify organization name for S3 path
// =============================================================================
function slugify(text: string): string {
  return text
    .toString()
    .toLowerCase()
    .normalize("NFD") // Decompose accented characters
    .replace(/[\u0300-\u036f]/g, "") // Remove diacritics
    .replace(/[^a-z0-9]+/g, "-") // Replace non-alphanumeric with hyphens
    .replace(/^-+|-+$/g, ""); // Remove leading/trailing hyphens
}

// =============================================================================
// POST /api/staff/virements-salaires/generate-pdf
// =============================================================================
export async function POST(req: NextRequest) {
  try {
    console.log("[generate-pdf] Starting PDF generation");
    
    // 1) Check auth
    const supabase = createRouteHandlerClient({ cookies });
    const {
      data: { session },
      error: sessionError,
    } = await supabase.auth.getSession();
    
    if (sessionError || !session) {
      console.error("[generate-pdf] Auth error:", sessionError);
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }
    
    const user = session.user;
    console.log("[generate-pdf] User authenticated:", user.id);

    // 2) Check if staff
    const { data: staffData, error: staffError } = await supabase
      .from("staff_users")
      .select("is_staff")
      .eq("user_id", user.id)
      .maybeSingle();
      
    const isStaff = staffData?.is_staff || false;
    console.log("[generate-pdf] Is staff:", isStaff);
    
    if (!isStaff) {
      return NextResponse.json({ error: "Forbidden: staff only" }, { status: 403 });
    }

    // 3) Parse request body
    const body = await req.json();
    const { salary_transfer_id } = body;
    console.log("[generate-pdf] Salary transfer ID:", salary_transfer_id);
    
    if (!salary_transfer_id) {
      return NextResponse.json({ error: "Missing salary_transfer_id" }, { status: 400 });
    }

    // 4) Get salary transfer details
    console.log("[generate-pdf] Fetching salary transfer...");
    const { data: salaryTransfer, error: stError } = await supabase
      .from("salary_transfers")
      .select("*")
      .eq("id", salary_transfer_id)
      .single();
    if (stError || !salaryTransfer) {
      console.error("[generate-pdf] Salary transfer fetch error:", stError);
      return NextResponse.json({ error: "Salary transfer not found", details: stError?.message }, { status: 404 });
    }
    console.log("[generate-pdf] Salary transfer found:", { org_id: salaryTransfer.org_id, period_month: salaryTransfer.period_month });

    // 5) Get organization details
    console.log("[generate-pdf] Fetching organization and details...");
    const { data: organization, error: orgError } = await supabase
      .from("organizations")
      .select("*")
      .eq("id", salaryTransfer.org_id)
      .single();
    if (orgError || !organization) {
      console.error("[generate-pdf] Organization fetch error:", orgError);
      return NextResponse.json({ error: "Organization not found", details: orgError?.message }, { status: 404 });
    }
    console.log("[generate-pdf] Organization found:", organization.name);

    // 5b) Get organization_details
    const { data: orgDetails, error: orgDetailsError } = await supabase
      .from("organization_details")
      .select("*")
      .eq("org_id", salaryTransfer.org_id)
      .single();
    if (orgDetailsError) {
      console.warn("[generate-pdf] orgDetails fetch error:", orgDetailsError);
    }
    console.log("[generate-pdf] Organization details loaded:", orgDetails ? "✓" : "✗");

    // 6) Get payslips based on selection mode
    console.log("[generate-pdf] Fetching payslips...");
    console.log("[generate-pdf] Selection mode:", salaryTransfer.selection_mode || 'period');
    console.log("[generate-pdf] Organization ID:", salaryTransfer.org_id);
    
    let payslips: any[] | null = null;
    let payslipsError: any = null;
    
    if (salaryTransfer.selection_mode === 'manual') {
      // Mode manuel: récupérer les paies liées via la table de liaison
      console.log("[generate-pdf] Manual mode: fetching linked payslips");
      
      const { data: linkedPayslips, error: linkedError } = await supabase
        .from("salary_transfer_payslips")
        .select(`
          payslip_id,
          custom_amount,
          payslips (
            *,
            cddu_contracts (
              employee_matricule,
              contract_number,
              analytique,
              profession,
              salaries (
                nom,
                prenom,
                iban
              )
            )
          )
        `)
        .eq("salary_transfer_id", salary_transfer_id);
        
      payslipsError = linkedError;
      
      if (!linkedError && linkedPayslips) {
        // Flatten the structure and add custom_amount to each payslip
        payslips = linkedPayslips
          .map(lp => {
            if (!lp.payslips) return null;
            return {
              ...lp.payslips,
              custom_amount: lp.custom_amount, // Ajouter le montant personnalisé
            };
          })
          .filter(p => p !== null);
        console.log("[generate-pdf] Found", payslips.length, "linked payslips");
        
        // Log custom amounts for debugging
        const withCustomAmounts = payslips.filter(p => p.custom_amount !== null).length;
        console.log("[generate-pdf] Payslips with custom amounts:", withCustomAmounts);
      }
    } else {
      // Mode période: récupérer toutes les paies du mois (comportement actuel)
      console.log("[generate-pdf] Period mode: fetching all payslips for period");
      const periodMonth = salaryTransfer.period_month; // Already in YYYY-MM-01 format
      console.log("[generate-pdf] Period month:", periodMonth);
      
      const { data: periodPayslips, error: periodError } = await supabase
        .from("payslips")
        .select(`
          *,
          cddu_contracts (
            employee_matricule,
            contract_number,
            analytique,
            profession,
            salaries (
              nom,
              prenom,
              iban
            )
          )
        `)
        .eq("organization_id", salaryTransfer.org_id)
        .eq("period_month", periodMonth);
        
      payslips = periodPayslips;
      payslipsError = periodError;
    }

    console.log("[generate-pdf] Payslips query result:", {
      error: payslipsError,
      count: payslips?.length || 0,
      sample: payslips?.[0] ? {
        id: payslips[0].id,
        net_amount: payslips[0].net_amount,
        has_contract: !!payslips[0].cddu_contracts,
        has_salarie: !!payslips[0].cddu_contracts?.salaries
      } : null
    });

    if (payslipsError) {
      console.error("[generate-pdf] Payslips fetch error:", payslipsError);
      return NextResponse.json({ 
        error: "Failed to fetch payslips", 
        details: (payslipsError as any)?.message || "Unknown error",
        debugInfo: {
          org_id: salaryTransfer.org_id,
          selection_mode: salaryTransfer.selection_mode,
          period_month: salaryTransfer.period_month
        }
      }, { status: 500 });
    }

    if (!payslips || payslips.length === 0) {
      console.warn("[generate-pdf] No payslips found!");
      console.warn("[generate-pdf] Query params:", {
        organization_id: salaryTransfer.org_id,
        selection_mode: salaryTransfer.selection_mode,
        period_month: salaryTransfer.period_month
      });
      // Continue anyway - we'll generate a PDF with empty payslips array
    } else {
      console.log("[generate-pdf] Found", payslips.length, "payslips");
      // Log details about contracts
      const withContracts = payslips.filter(p => p.cddu_contracts).length;
      const withSalaries = payslips.filter(p => p.cddu_contracts?.salaries).length;
      console.log("[generate-pdf] Payslips with contracts:", withContracts);
      console.log("[generate-pdf] Payslips with salaries:", withSalaries);
      
      // Log first payslip sample
      console.log("[generate-pdf] First payslip sample:", JSON.stringify(payslips[0], null, 2));
    }

    // 7) Build PDFMonkey payload
    console.log("═══════════════════════════════════════════════════════════");
    console.log("[generate-pdf] 🔍 BUILDING PDFMONKEY PAYLOAD");
    console.log("[generate-pdf] 📊 Payslips count:", payslips?.length || 0);
    console.log("═══════════════════════════════════════════════════════════");
    
    // Build line items for payslips
    const lineItems = (payslips || []).map((p: any) => {
      const contract = p.cddu_contracts;
      const salarie = contract?.salaries;
      
      // Get employee name
      const employee_name = `${salarie?.prenom || ""} ${salarie?.nom || ""}`.trim();
      
      // Utiliser le montant personnalisé si disponible, sinon le montant de la paie
      const montant = p.custom_amount !== null && p.custom_amount !== undefined
        ? parseFloat(p.custom_amount)
        : parseFloat(p.net_after_withholding || p.net_amount || 0);
      
      console.log("[generate-pdf] 👤 Processing payslip:", {
        payslip_id: p.id,
        has_contract: !!contract,
        has_salarie: !!salarie,
        employee_name,
        net_amount: p.net_amount,
        net_after_withholding: p.net_after_withholding,
        custom_amount: p.custom_amount,
        final_montant: montant
      });
      
      return {
        employee_name,
        matricule: contract?.employee_matricule || "",
        contrat: contract?.contract_number || "",
        montant,
        analytique: contract?.analytique || "",
        profession: contract?.profession || "",
      };
    });
    
    console.log("[generate-pdf] ✅ Line items built:", lineItems.length, "items");
    if (lineItems.length > 0) {
      console.log("[generate-pdf] 📝 First line item:", JSON.stringify(lineItems[0], null, 2));
    }

    // Calculate totals
    const totalNet = (payslips || []).reduce((sum: number, p: any) => {
      // Utiliser le montant personnalisé si disponible, sinon le montant de la paie
      const amount = p.custom_amount !== null && p.custom_amount !== undefined
        ? (typeof p.custom_amount === "string" ? parseFloat(p.custom_amount) : p.custom_amount)
        : (typeof p.net_after_withholding === "string" 
            ? parseFloat(p.net_after_withholding) 
            : (p.net_after_withholding || (typeof p.net_amount === "string" ? parseFloat(p.net_amount) : p.net_amount) || 0));
      return sum + amount;
    }, 0);
    console.log("[generate-pdf] Total net amount:", totalNet);

    // Get callsheet date (date d'appel)
    const callsheetDate = formatDateFR(salaryTransfer.callsheet_date || salaryTransfer.created_at);
    
    // Get limit date (date d'échéance)
    const limitDate = formatDateFR(salaryTransfer.deadline);
    
    // Calculate number of payslips
    const nbrePayslips = payslips?.length || 0;
    
    // Generate transfer reference using code_employeur from organization_details
    const codeEmployeur = orgDetails?.code_employeur || organization.code || "ORG";
    const transferReference = `${codeEmployeur}-${salaryTransfer.num_appel || "00000"}`;
    
    console.log("═══════════════════════════════════════════════════════════");
    console.log("[generate-pdf] 📋 PAYLOAD SUMMARY:");
    console.log("[generate-pdf] Transfer reference:", transferReference);
    console.log("[generate-pdf] Total net:", totalNet);
    console.log("[generate-pdf] Number of payslips:", nbrePayslips);
    console.log("[generate-pdf] Number of line items:", lineItems.length);
    console.log("═══════════════════════════════════════════════════════════");

    const pdfMonkeyPayload = {
      document: {
        document_template_id: "F4BCB5FF-1AB1-4CEE-B57F-82A6B9893E9E",
        status: "pending",
        payload: {
          // Client information (simplified from organization)
          client_address: orgDetails?.adresse || "",
          client_cp: orgDetails?.cp || "",
          client_city: orgDetails?.ville || "",
          client_code: organization.code || "",
          client_name: organization.name || "",
          
          // Callsheet information
          callsheet_date: callsheetDate,
          limit_date: limitDate,
          callsheet_number: salaryTransfer.num_appel || "00000",
          transfer_method: salaryTransfer.mode || "Virement SEPA",
          
          // Period and amounts
          periode: salaryTransfer.period_label || formatMonthPeriod(salaryTransfer.period_month),
          total_salaires_nets: totalNet,
          solde_compte_client: 0.0, // À implémenter si nécessaire
          total_transfer: totalNet, // Pour l'instant, même que total_salaires_nets
          deposit: 0.0, // À implémenter si nécessaire
          
          // Payslip count and reference
          nbre_paies: nbrePayslips,
          transfer_reference: transferReference,
          
          // Line items (payslips array)
          lineItems: lineItems,
        },
        meta: {},
      },
    };
    
    console.log("═══════════════════════════════════════════════════════════");
    console.log("[generate-pdf] 🚀 FINAL PAYLOAD TO PDFMONKEY:");
    console.log("[generate-pdf] Payload prepared with", lineItems.length, "payslips");
    console.log("[generate-pdf] lineItems in payload:", pdfMonkeyPayload.document.payload.lineItems.length);
    console.log("═══════════════════════════════════════════════════════════");
    
    if (lineItems.length === 0) {
      console.warn("[generate-pdf] ⚠️ WARNING: Payload has no payslips!");
      console.warn("[generate-pdf] This will generate an empty PDF!");
    } else {
      console.log("[generate-pdf] ✅ Sample line item in payload:", JSON.stringify(lineItems[0], null, 2));
    }

    // 8) Call PDFMonkey API
    console.log("[generate-pdf] 📤 Calling PDFMonkey API...");
    const pdfMonkeyUrl = process.env.PDFMONKEY_URL || "https://api.pdfmonkey.io/api/v1/documents";
    const pdfMonkeyApiKey = process.env.PDFMONKEY_API_KEY;
    if (!pdfMonkeyApiKey) {
      console.error("[generate-pdf] Missing PDFMONKEY_API_KEY");
      return NextResponse.json({ error: "Missing PDFMONKEY_API_KEY" }, { status: 500 });
    }

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

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

    const createData = await createRes.json();
    console.log("[generate-pdf] PDFMonkey response:", createData);
    
    const documentId = createData.document?.id;
    if (!documentId) {
      console.error("[generate-pdf] 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("[generate-pdf] Document URL for polling:", documentUrl);

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

    // 10) Download PDF
    console.log("[generate-pdf] Downloading PDF from:", download_url);
    const pdfRes = await fetch(download_url);
    if (!pdfRes.ok) {
      console.error("[generate-pdf] 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("[generate-pdf] PDF downloaded, size:", pdfBuffer.length, "bytes");

    // 11) Upload to S3
    console.log("[generate-pdf] Uploading to S3...");
    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!,
      },
    });

    const bucketName = "odentas-docs";
    const clientSlug = slugify(organization.name || "client");
    const s3Key = `documents/${clientSlug}/appel-virement/${salary_transfer_id}-${Date.now()}.pdf`;
    console.log("[generate-pdf] S3 target:", { bucket: bucketName, key: s3Key });

    const uploadCommand = new PutObjectCommand({
      Bucket: bucketName,
      Key: s3Key,
      Body: pdfBuffer,
      ContentType: "application/pdf",
    });
    await s3Client.send(uploadCommand);
    console.log("[generate-pdf] S3 upload successful");

    // Generate a presigned URL valid for 7 days
    const getObjectCommand = new GetObjectCommand({
      Bucket: bucketName,
      Key: s3Key,
    });
    const s3Url = await getSignedUrl(s3Client, getObjectCommand, { expiresIn: 604800 }); // 7 days in seconds
    console.log("[generate-pdf] Presigned URL generated (expires in 7 days)");

    // 12) Update salary_transfers with callsheet_url
    console.log("[generate-pdf] Updating salary_transfers table...");
    const { error: updateError } = await supabase
      .from("salary_transfers")
      .update({
        callsheet_url: s3Url,
        updated_at: new Date().toISOString(),
      })
      .eq("id", salary_transfer_id);

    if (updateError) {
      console.error("[generate-pdf] Failed to update salary_transfers:", updateError);
      return NextResponse.json(
        { error: "PDF generated but failed to update database", url: s3Url, details: updateError.message },
        { status: 500 }
      );
    }
    console.log("[generate-pdf] Database updated successfully");

    // 13) Return success
    console.log("[generate-pdf] PDF generation complete!");
    return NextResponse.json({
      success: true,
      callsheet_url: s3Url,
      payslips_count: payslips?.length || 0,
      total_net: totalNet,
    });
  } catch (err: any) {
    console.error("[generate-pdf] Unexpected error:", err);
    console.error("[generate-pdf] Stack trace:", err.stack);
    return NextResponse.json({ 
      error: err.message || "Internal server error",
      stack: process.env.NODE_ENV === 'development' ? err.stack : undefined 
    }, { status: 500 });
  }
}
