// app/api/staff/facturation/bulk-gocardless/route.ts
import { NextResponse } from "next/server";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { cleanEnv } from "@/lib/cleanEnv";

export const dynamic = 'force-dynamic';
export const revalidate = 0;
export const runtime = 'nodejs';

async function isStaffUser(supabase: any, userId: string): Promise<boolean> {
  try {
    const { data: staffRow } = await supabase
      .from('staff_users')
      .select('is_staff')
      .eq('user_id', userId)
      .maybeSingle();
    return !!staffRow?.is_staff;
  } catch {
    return false;
  }
}

async function createGoCardlessPayment(invoiceData: any, mandateId: string) {
  const apiUrl = cleanEnv('GOCARDLESS_ENVIRONMENT') === 'live' 
    ? 'https://api.gocardless.com' 
    : 'https://api-sandbox.gocardless.com';
  
  const accessToken = cleanEnv('GOCARDLESS_ACCESS_TOKEN');
  if (!accessToken) throw new Error("Missing GOCARDLESS_ACCESS_TOKEN");

  // Helpers
  const toISODate = (d: Date) => d.toISOString().slice(0, 10);
  const parseDate = (v?: string | null): Date | null => {
    if (!v) return null;
    const d = new Date(v);
    return isNaN(d.getTime()) ? null : d;
  };

  // Try to fetch mandate's next_possible_charge_date
  let nextPossible: string | null = null;
  try {
    const res = await fetch(`${apiUrl}/mandates/${mandateId}`, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json',
        'GoCardless-Version': '2015-07-06'
      }
    });
    if (res.ok) {
      const json = await res.json();
      nextPossible = json?.mandates?.next_possible_charge_date || json?.mandate?.next_possible_charge_date || null;
    }
  } catch (e) {
    // Non bloquant: on continue sans nextPossible
  }

  // Determine target charge date
  const desiredDate = parseDate(invoiceData.sepa_day) || parseDate(invoiceData.due_date);
  const today = new Date();
  let chargeDate: string | undefined = undefined;

  if (desiredDate) {
    // Ensure not before today
    let adjusted = desiredDate < today ? today : desiredDate;
    // Ensure not before mandate's next_possible_charge_date
    if (nextPossible) {
      const np = parseDate(nextPossible);
      if (np && adjusted < np) adjusted = np;
    }
    chargeDate = toISODate(adjusted);
  } else if (nextPossible) {
    chargeDate = nextPossible;
  } // else: omit charge_date to let GC pick earliest

  const basePayment = {
    amount: Math.round((invoiceData.amount_ttc || 0) * 100), // Montant en centimes
    currency: 'EUR',
    reference: `ODENTAS ${invoiceData.invoice_number || invoiceData.id.slice(0, 8)}`,
    description: `ODENTAS ${invoiceData.invoice_number || invoiceData.id.slice(0, 8)}`,
    links: { mandate: mandateId },
  } as any;
  if (chargeDate) basePayment.charge_date = chargeDate;

  const paymentData = { payments: basePayment };

  const response = await fetch(`${apiUrl}/payments`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
      'GoCardless-Version': '2015-07-06'
    },
    body: JSON.stringify(paymentData)
  });

  if (!response.ok) {
    const error = await response.json().catch(() => ({}));
    // If validation on charge_date, retry without charge_date to let GC schedule automatically
    const errors: any[] = error?.error?.errors || [];
    const chargeDateError = errors.find(e => String(e?.field || '').includes('charge_date'));
    if (chargeDateError && basePayment.charge_date) {
      delete basePayment.charge_date;
      const retry = await fetch(`${apiUrl}/payments`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${accessToken}`,
          'Content-Type': 'application/json',
          'GoCardless-Version': '2015-07-06'
        },
        body: JSON.stringify({ payments: basePayment })
      });
      if (!retry.ok) {
        const retryErr = await retry.json().catch(() => ({}));
        throw new Error(`GoCardless API error: ${JSON.stringify(retryErr)}`);
      }
      return retry.json();
    }
    throw new Error(`GoCardless API error: ${JSON.stringify(error)}`);
  }

  return response.json();
}

export async function POST(req: Request) {
  try {
    console.log('[api/staff/facturation/bulk-gocardless] POST request');
    
    const supabase = createRouteHandlerClient({ cookies });
    const { data: { session } } = await supabase.auth.getSession();
    if (!session) return NextResponse.json({ error: 'unauthorized' }, { status: 401 });

    // Vérifier que l'utilisateur est staff
    const isStaff = await isStaffUser(supabase, session.user.id);
    if (!isStaff) {
      return NextResponse.json({ error: 'forbidden', message: 'Staff access required' }, { status: 403 });
    }

    const { invoiceIds } = await req.json();
    
    if (!invoiceIds || !Array.isArray(invoiceIds) || invoiceIds.length === 0) {
      return NextResponse.json({ error: 'invalid_input', message: 'Liste des factures requise' }, { status: 400 });
    }

    console.log(`[api/staff/facturation/bulk-gocardless] Processing ${invoiceIds.length} invoices`);

    const results = [];
    const errors = [];

    for (const invoiceId of invoiceIds) {
      try {
        // Récupérer la facture avec les informations de l'organisation
        const { data: invoice, error: invoiceError } = await supabase
          .from('invoices')
          .select(`
            *,
            organizations!inner(
              id,
              structure_api,
              organization_details!inner(
                id_mandat_sepa
              )
            )
          `)
          .eq('id', invoiceId)
          .single();

        if (invoiceError) {
          console.error(`[api/staff/facturation/bulk-gocardless] Invoice error for ${invoiceId}:`, invoiceError);
          errors.push({ invoiceId, error: 'invoice_not_found' });
          continue;
        }

        const organization = invoice.organizations;
        const organizationDetails = organization.organization_details;
        
        if (!organizationDetails.id_mandat_sepa) {
          errors.push({ invoiceId, error: 'no_sepa_mandate' });
          continue;
        }

        // Vérifier que la facture est dans un statut valide (brouillon ou en_cours)
        if (invoice.status !== 'brouillon' && invoice.status !== 'en_cours') {
          errors.push({ invoiceId, error: 'invalid_status' });
          continue;
        }

        // Vérifier si la facture n'est pas déjà émise (double vérification)
        if (invoice.status === 'emise') {
          errors.push({ invoiceId, error: 'already_emitted' });
          continue;
        }

        console.log(`[api/staff/facturation/bulk-gocardless] Creating GoCardless payment for invoice ${invoiceId}...`);
        
        // Créer le paiement GoCardless
        const gcPayment = await createGoCardlessPayment(invoice, organizationDetails.id_mandat_sepa);
        
        console.log(`[api/staff/facturation/bulk-gocardless] GoCardless payment created for ${invoiceId}:`, gcPayment.payments.id);

        // Marquer la facture comme émise
        const { error: updateError } = await supabase
          .from('invoices')
          .update({
            status: 'emise',
            updated_at: new Date().toISOString()
          })
          .eq('id', invoiceId);

        if (updateError) {
          console.error(`[api/staff/facturation/bulk-gocardless] Update error for ${invoiceId}:`, updateError);
          errors.push({ invoiceId, error: 'update_failed' });
          continue;
        }

        results.push({ 
          invoiceId, 
          success: true, 
          gocardless_payment_id: gcPayment.payments.id 
        });

      } catch (error) {
        console.error(`[api/staff/facturation/bulk-gocardless] Error processing invoice ${invoiceId}:`, error);
        const message = error instanceof Error ? error.message : String(error);
        errors.push({ invoiceId, error: 'processing_error', message });
      }
    }

    console.log(`[api/staff/facturation/bulk-gocardless] Bulk operation completed: ${results.length} success, ${errors.length} errors`);

    return NextResponse.json({
      success: true,
      message: `${results.length} paiement(s) GoCardless créé(s) avec succès`,
      results,
      errors,
      summary: {
        total: invoiceIds.length,
        success: results.length,
        failed: errors.length
      }
    });

  } catch (error) {
    console.error('[api/staff/facturation/bulk-gocardless] Error:', error);
    const message = error instanceof Error ? error.message : String(error);
    return NextResponse.json({ 
      error: 'internal_server_error', 
      message 
    }, { status: 500 });
  }
}