// app/api/staff/facturation/[id]/launch/route.ts
import { NextResponse } from "next/server";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { sendInvoiceEmail as sendUniversalInvoiceEmail } from "@/lib/emailMigrationHelpers";
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;
  }
}

// construit un message personnalisé selon le type de facture
function buildInvoiceCustomMessage(invoice: any): string {
  switch (invoice.invoice_type) {
    case 'paie_mensuelle':
      // Cas spécial pour les paiements par virement
      if (invoice.payment_method === 'virement') {
        const periodText = invoice.period_label ? `pour la période ${invoice.period_label}` : 'mensuelle';
        return `Votre facture ${periodText} est disponible. Vous trouverez ci-dessous nos coordonnées bancaires pour le virement.`;
      }
      // Cas normal (SEPA)
      return invoice.period_label ? `Votre facture pour la période ${invoice.period_label} est disponible et sera prélevée à la date indiquée ci-dessous` : `Votre facture mensuelle est disponible et sera prélevée à la date indiquée ci-dessous`;
    case 'paie_ouverture':
      return `Votre facture d'ouverture de compte est disponible et sera prélevée à la date indiquée ci-dessous`;
    case 'studio_site_web':
      const siteNameCreation = invoice.site_name || '';
      if (invoice.payment_method === 'virement') {
        return `Votre facture pour la création de votre site web ${siteNameCreation} est disponible. Vous trouverez ci-dessous nos coordonnées bancaires pour effectuer le virement.<br><br>Toute l'équipe Odentas vous remercie pour votre confiance et reste à votre disposition pour toute question, en réponse de cet e-mail ou sur WhatsApp au <a href="https://wa.me/33780978000" style="color:#0B5FFF; text-decoration:none;">07 80 978 000</a>.`.trim();
      }
      return `Votre facture pour la création du site web ${siteNameCreation} est disponible et sera prélevée à la date indiquée ci-dessous.`.trim();
    case 'studio_renouvellement':
      const siteNameRenewal = invoice.site_name || '';
      if (invoice.payment_method === 'virement') {
        return `Votre facture pour le renouvellement de l'hébergement de votre site web ${siteNameRenewal} est disponible. Vous trouverez ci-dessous nos coordonnées bancaires pour effectuer le virement.<br><br>Toute l'équipe Odentas vous remercie pour votre confiance et reste à votre disposition pour toute question, en réponse de cet e-mail ou sur WhatsApp au <a href="https://wa.me/33780978000" style="color:#0B5FFF; text-decoration:none;">07 80 978 000</a>.`.trim();
      }
      return `Votre facture pour le renouvellement du site web ${siteNameRenewal} est disponible et sera prélevée à la date indiquée ci-dessous.`.trim();
    default:
      return 'Votre facture';
  }
}

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;
    // Accepts YYYY-MM-DD or ISO strings
    const dt = new Date(v);
    return isNaN(dt.getTime()) ? null : dt;
  };

  // Fetch mandate to get 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, { params }: { params: { id: string } }) {
  try {
    console.log('[api/staff/facturation/[id]/launch] POST request for ID:', params.id);
    
    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 });
    }

    // 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(
            email_notifs,
            email_notifs_cc,
            id_mandat_sepa,
            prenom_contact,
            code_employeur
          )
        )
      `)
      .eq('id', params.id)
      .single();

    if (invoiceError) {
      console.error('[api/staff/facturation/[id]/launch] Invoice error:', invoiceError);
      return NextResponse.json({ error: 'invoice_not_found' }, { status: 404 });
    }

    // Vérifier si la facture n'a pas déjà été lancée
    if (invoice.status === 'emise' || invoice.notified === true) {
      console.log('[api/staff/facturation/[id]/launch] Invoice already launched:', {
        id: params.id,
        status: invoice.status,
        notified: invoice.notified
      });
      return NextResponse.json({ 
        error: 'already_launched',
        message: 'Cette facture a déjà été lancée'
      }, { status: 400 });
    }

  const organization = invoice.organizations;
  const organizationDetails = organization.organization_details;
    
    if (!organizationDetails.email_notifs) {
      return NextResponse.json({ error: 'no_notification_email' }, { status: 400 });
    }

    if (!organizationDetails.id_mandat_sepa) {
      return NextResponse.json({ error: 'no_sepa_mandate' }, { status: 400 });
    }

    console.log('[api/staff/facturation/[id]/launch] Creating GoCardless payment...');
    
    // Créer le paiement GoCardless
    const gcPayment = await createGoCardlessPayment(invoice, organizationDetails.id_mandat_sepa);
    
    console.log('[api/staff/facturation/[id]/launch] GoCardless payment created:', gcPayment.payments.id);

    // Envoyer l'email de notification
    console.log('[api/staff/facturation/[id]/launch] Sending notification email...');
    
    // Utiliser le prénom du contact directement
  const firstName = organizationDetails.prenom_contact || "";
  const organizationName: string | undefined = organization?.structure_api || undefined;
    
    const amountFormatted = new Intl.NumberFormat("fr-FR", { style: "currency", currency: "EUR" }).format(invoice.amount_ttc || 0);
    const customMessage = buildInvoiceCustomMessage(invoice);
    
    // Pour les factures studio, utiliser le lien de téléchargement direct
    // Pour les factures paie, utiliser l'Espace Paie
    const isStudioInvoice = invoice.invoice_type === 'studio_renouvellement' || invoice.invoice_type === 'studio_site_web';
    const ctaUrl = isStudioInvoice 
      ? `${process.env.NEXT_PUBLIC_SITE_URL}/api/public/invoices/${invoice.id}/download`
      : `${process.env.NEXT_PUBLIC_SITE_URL}/facturation`;
    
    console.log('[api/staff/facturation/[id]/launch] Email data:', {
      isStudioInvoice,
      invoiceType: invoice.invoice_type,
      ctaUrl,
      invoiceId: invoice.id,
      siteUrl: process.env.NEXT_PUBLIC_SITE_URL
    });
    
    await sendUniversalInvoiceEmail(
      organizationDetails.email_notifs,
      organizationDetails.email_notifs_cc,
      {
        firstName,
        organizationName,
        employerCode: organizationDetails.code_employeur || undefined,
        invoiceNumber: invoice.invoice_number || invoice.id.slice(0, 8),
        amount: amountFormatted,
        customMessage,
        invoiceDate: invoice.invoice_date ? new Date(invoice.invoice_date).toLocaleDateString('fr-FR') : undefined,
        sepaDate: invoice.sepa_day ? new Date(invoice.sepa_day).toLocaleDateString('fr-FR') : undefined,
        ctaUrl,
        invoiceType: invoice.invoice_type,
        paymentMethod: invoice.payment_method || undefined,
        siteName: invoice.site_name || undefined,
      }
    );

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

    if (updateError) {
      console.error('[api/staff/facturation/[id]/launch] Update error:', updateError);
      return NextResponse.json({ 
        error: 'update_failed', 
        message: `Erreur lors de la mise à jour: ${updateError.message}` 
      }, { status: 500 });
    }

    console.log('[api/staff/facturation/[id]/launch] Invoice launched successfully');

    return NextResponse.json({
      success: true,
      message: 'Facture lancée avec succès',
      gocardless_payment_id: gcPayment.payments.id
    });

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