/**
 * Ad Ops Invoice Service
 * Creates MoonInvoice invoices for ad campaigns using MOONINVOICE_API_KEY_RMP
 */

import { createClient } from '@/lib/supabase/server';
import { moonCreateContact, moonGetContacts, moonCreateInvoice } from '@/lib/billing/moonInvoiceClient';

export interface CampaignInvoiceParams {
  campaignId: string;
  clientName: string;
  clientEmail?: string;
  publication: string;
  placementZone: string;
  startDate: string;
  endDate: string;
  agreedRate: number;
  campaignDescription?: string;
}

export async function createAdOpsMoonInvoice(params: CampaignInvoiceParams): Promise<{
  success: boolean;
  invoiceId?: string;
  invoiceNumber?: string;
  error?: string;
}> {
  try {
    // Step 1: Find or create contact in MoonInvoice (RMP company)
    let contactId: string | undefined;

    try {
      const contacts = await moonGetContacts('rmp', 1);
      const existing = contacts?.data?.find(
        (c: any) =>
          c.name?.toLowerCase() === params.clientName.toLowerCase() ||
          (params.clientEmail && c.email?.toLowerCase() === params.clientEmail.toLowerCase())
      );
      if (existing) {
        contactId = existing.id || existing.ContactID;
      }
    } catch {
      // Contact search failed — will try to create
    }

    if (!contactId) {
      const newContact = await moonCreateContact('rmp', {
        name: params.clientName,
        email: params.clientEmail || '',
        type: 'client',
      });
      contactId = newContact?.id || newContact?.ContactID;
    }

    if (!contactId) {
      throw new Error('Could not find or create MoonInvoice contact');
    }

    // Step 2: Calculate due date (Net 30 from start date)
    const startDateObj = new Date(params.startDate);
    const dueDate = new Date(startDateObj);
    dueDate.setDate(dueDate.getDate() + 30);
    const dueDateStr = dueDate.toISOString().split('T')[0];

    const description = params.campaignDescription ||
      `${params.publication} Banner Ad — ${params.placementZone} | Dates: ${params.startDate} - ${params.endDate}`;

    // Step 3: Create invoice in MoonInvoice
    const invoice = await moonCreateInvoice('rmp', {
      ContactID: contactId,
      InvoiceDate: params.startDate,
      DueDate: dueDateStr,
      LineItems: [
        {
          description,
          quantity: 1,
          rate: params.agreedRate,
          amount: params.agreedRate,
        },
      ],
      Notes: `Campaign ID: ${params.campaignId} | Publication: ${params.publication} | Dates: ${params.startDate} - ${params.endDate} | Placement: ${params.placementZone}`,
    });

    const invoiceId = invoice?.id || invoice?.InvoiceID;
    const invoiceNumber = invoice?.invoice_number || invoice?.InvoiceNumber;

    if (!invoiceId) {
      throw new Error('Invoice created but no ID returned');
    }

    // Step 4: Update ad_campaigns with invoice reference
    const supabase = await createClient();
    await supabase
      .from('ad_campaigns')
      .update({
        mooninvoice_invoice_id: String(invoiceId),
        invoice_id: invoiceNumber || String(invoiceId),
        mooninvoice_contact_id: String(contactId),
        updated_at: new Date().toISOString(),
      })
      .eq('id', params.campaignId);

    return { success: true, invoiceId: String(invoiceId), invoiceNumber };
  } catch (err: any) {
    // Store in pending_invoices for retry
    try {
      const supabase = await createClient();
      const nextRetry = new Date();
      nextRetry.setMinutes(nextRetry.getMinutes() + 30);

      await supabase.from('adops_pending_invoices').insert({
        campaign_id: params.campaignId,
        client_name: params.clientName,
        client_email: params.clientEmail,
        invoice_data: params as any,
        retry_count: 0,
        next_retry_at: nextRetry.toISOString(),
        status: 'pending',
        error_message: err.message,
      });
    } catch {
      // Ignore secondary error
    }

    return { success: false, error: err.message };
  }
}

export async function retryPendingInvoices(): Promise<void> {
  const supabase = await createClient();

  const { data: pending } = await supabase
    .from('adops_pending_invoices')
    .select('*')
    .in('status', ['pending', 'retrying'])
    .lte('next_retry_at', new Date().toISOString())
    .lt('retry_count', 48); // Max 48 retries = 24 hours at 30min intervals

  if (!pending?.length) return;

  for (const item of pending) {
    const result = await createAdOpsMoonInvoice(item.invoice_data as CampaignInvoiceParams);

    if (result.success) {
      await supabase
        .from('adops_pending_invoices')
        .update({ status: 'created', updated_at: new Date().toISOString() })
        .eq('id', item.id);
    } else {
      const nextRetry = new Date();
      nextRetry.setMinutes(nextRetry.getMinutes() + 30);

      await supabase
        .from('adops_pending_invoices')
        .update({
          retry_count: item.retry_count + 1,
          last_retry_at: new Date().toISOString(),
          next_retry_at: nextRetry.toISOString(),
          status: item.retry_count >= 47 ? 'failed' : 'retrying',
          error_message: result.error,
          updated_at: new Date().toISOString(),
        })
        .eq('id', item.id);
    }
  }
}
