// AR Dunning Automation System
// Auto-sends payment reminders at 7/14/30 days overdue

import prisma from '@/lib/db';
import { logSimpleAction } from './agent-logger';
import { BRAND } from '@/lib/white-label/constants';

/** Escape HTML entities to prevent XSS in email templates */
function escapeHtml(str: string): string {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

export interface DunningConfig {
  level1DaysOverdue: number;  // Default: 7
  level2DaysOverdue: number;  // Default: 14
  level3DaysOverdue: number;  // Default: 30
  autoSendEmails: boolean;
}

const DEFAULT_CONFIG: DunningConfig = {
  level1DaysOverdue: 7,
  level2DaysOverdue: 14,
  level3DaysOverdue: 30,
  autoSendEmails: true,
};

export interface DunningResult {
  arId: string;
  invoiceId: string;
  customerEmail: string;
  previousLevel: number;
  newLevel: number;
  emailSent: boolean;
  action: string;
}

function generateDunningEmail(level: number, arRecord: {
  invoiceId: string;
  customerName: string;
  amountDue: number;
  dueDate: Date;
  daysPastDue: number;
}): { subject: string; htmlContent: string; notificationId: string } {
  const { invoiceId, customerName: rawName, amountDue, dueDate, daysPastDue } = arRecord;
  const customerName = escapeHtml(rawName);
  const formattedAmount = `$${amountDue.toFixed(2)}`;
  const formattedDueDate = dueDate.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
  
  const baseStyle = `
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    background: linear-gradient(135deg, #0C1222 0%, #1a1f3a 100%);
    color: #e2e8f0;
  `;
  
  if (level === 1) {
    return {
      subject: `Friendly Reminder: Invoice ${invoiceId} - Payment Due`,
      notificationId: process.env.NOTIF_ID_AR_DUNNING_REMINDER || '',
      htmlContent: `
        <div style="${baseStyle} padding: 40px; border-radius: 12px;">
          <div style="max-width: 600px; margin: 0 auto;">
            <div style="text-align: center; margin-bottom: 30px;">
              <h1 style="color: #0EA5E9; margin: 0;">👻 ${BRAND.companyName}</h1>
            </div>
            <h2 style="color: #f1f5f9;">Hi ${customerName},</h2>
            <p style="font-size: 16px; line-height: 1.6;">
              Just a friendly reminder that invoice <strong style="color: #0EA5E9;">${invoiceId}</strong> 
              for <strong style="color: #22c55e;">${formattedAmount}</strong> was due on ${formattedDueDate}.
            </p>
            <p style="font-size: 16px; line-height: 1.6;">
              It's now <strong>${daysPastDue} days</strong> past due. If you've already sent payment, 
              please disregard this message—it may have crossed in transit.
            </p>
            <div style="background: rgba(6, 182, 212, 0.1); border: 1px solid #0EA5E9; border-radius: 8px; padding: 20px; margin: 20px 0;">
              <p style="margin: 0; font-size: 14px;">
                <strong>Invoice:</strong> ${invoiceId}<br/>
                <strong>Amount Due:</strong> ${formattedAmount}<br/>
                <strong>Original Due Date:</strong> ${formattedDueDate}
              </p>
            </div>
            <p style="font-size: 14px; color: #94a3b8;">
              If you have any questions, just reply to this email—we're here to help.
            </p>
            <p style="font-size: 14px; color: #64748b; margin-top: 30px;">
              — The ${BRAND.companyName} Team
            </p>
          </div>
        </div>
      `
    };
  } else if (level === 2) {
    return {
      subject: `Important: Invoice ${invoiceId} - Payment ${daysPastDue} Days Overdue`,
      notificationId: process.env.NOTIF_ID_AR_DUNNING_WARNING || '',
      htmlContent: `
        <div style="${baseStyle} padding: 40px; border-radius: 12px;">
          <div style="max-width: 600px; margin: 0 auto;">
            <div style="text-align: center; margin-bottom: 30px;">
              <h1 style="color: #f59e0b; margin: 0;">⚠️ ${BRAND.companyName}</h1>
            </div>
            <h2 style="color: #f1f5f9;">Hi ${customerName},</h2>
            <p style="font-size: 16px; line-height: 1.6;">
              We noticed that invoice <strong style="color: #f59e0b;">${invoiceId}</strong> 
              for <strong style="color: #22c55e;">${formattedAmount}</strong> is now 
              <strong style="color: #f59e0b;">${daysPastDue} days overdue</strong>.
            </p>
            <p style="font-size: 16px; line-height: 1.6;">
              To avoid any service interruptions, please arrange payment at your earliest convenience.
            </p>
            <div style="background: rgba(245, 158, 11, 0.1); border: 1px solid #f59e0b; border-radius: 8px; padding: 20px; margin: 20px 0;">
              <p style="margin: 0; font-size: 14px;">
                <strong>Invoice:</strong> ${invoiceId}<br/>
                <strong>Amount Due:</strong> ${formattedAmount}<br/>
                <strong>Days Overdue:</strong> ${daysPastDue}
              </p>
            </div>
            <p style="font-size: 14px; color: #94a3b8;">
              If there's an issue with this invoice or you need to discuss payment arrangements, 
              please reach out immediately.
            </p>
            <p style="font-size: 14px; color: #64748b; margin-top: 30px;">
              — The ${BRAND.companyName} Team
            </p>
          </div>
        </div>
      `
    };
  } else {
    return {
      subject: `Final Notice: Invoice ${invoiceId} - Immediate Payment Required`,
      notificationId: process.env.NOTIF_ID_AR_FINAL_NOTICE || '',
      htmlContent: `
        <div style="${baseStyle} padding: 40px; border-radius: 12px;">
          <div style="max-width: 600px; margin: 0 auto;">
            <div style="text-align: center; margin-bottom: 30px;">
              <h1 style="color: #ef4444; margin: 0;">🚨 ${BRAND.companyName}</h1>
            </div>
            <h2 style="color: #f1f5f9;">Hi ${customerName},</h2>
            <p style="font-size: 16px; line-height: 1.6;">
              This is a <strong style="color: #ef4444;">final notice</strong> regarding invoice 
              <strong style="color: #ef4444;">${invoiceId}</strong> for 
              <strong style="color: #22c55e;">${formattedAmount}</strong>.
            </p>
            <p style="font-size: 16px; line-height: 1.6;">
              This invoice is now <strong style="color: #ef4444;">${daysPastDue} days overdue</strong>. 
              Immediate payment is required to prevent service suspension and potential collection action.
            </p>
            <div style="background: rgba(239, 68, 68, 0.1); border: 1px solid #ef4444; border-radius: 8px; padding: 20px; margin: 20px 0;">
              <p style="margin: 0; font-size: 14px;">
                <strong>Invoice:</strong> ${invoiceId}<br/>
                <strong>Amount Due:</strong> ${formattedAmount}<br/>
                <strong>Days Overdue:</strong> ${daysPastDue}<br/>
                <strong>Status:</strong> <span style="color: #ef4444;">FINAL NOTICE</span>
              </p>
            </div>
            <p style="font-size: 14px; color: #94a3b8;">
              Please process payment immediately or contact us to discuss resolution options.
            </p>
            <p style="font-size: 14px; color: #64748b; margin-top: 30px;">
              — The ${BRAND.companyName} Team
            </p>
          </div>
        </div>
      `
    };
  }
}

async function sendDunningEmail(
  email: string,
  subject: string,
  htmlContent: string,
  notificationId: string
): Promise<boolean> {
  try {
    const response = await fetch('https://apps.abacus.ai/api/sendNotificationEmail', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        api_key: process.env.ABACUSAI_API_KEY,
        app_id: process.env.WEB_APP_ID,
        notification_id: notificationId,
        recipient_email: email,
        subject: subject,
        body_html: htmlContent,
      }),
    });
    return response.ok;
  } catch (error) {
    console.error('Failed to send dunning email:', error);
    return false;
  }
}

export async function processDunning(
  config: DunningConfig = DEFAULT_CONFIG
): Promise<DunningResult[]> {
  const results: DunningResult[] = [];
  const now = new Date();
  
  // Get all open/overdue AR records
  const overdueRecords = await prisma.accountsReceivable.findMany({
    where: {
      status: { in: ['open', 'overdue'] },
      dueDate: { lt: now },
    },
    orderBy: { dueDate: 'asc' },
  });
  
  for (const ar of overdueRecords) {
    const daysPastDue = Math.floor(
      (now.getTime() - ar.dueDate.getTime()) / (1000 * 60 * 60 * 24)
    );
    
    // Update days past due
    await prisma.accountsReceivable.update({
      where: { id: ar.id },
      data: { daysPastDue, status: 'overdue' },
    });
    
    let newLevel = ar.dunningLevel;
    let shouldSendEmail = false;
    
    // Determine new dunning level
    if (daysPastDue >= config.level3DaysOverdue && ar.dunningLevel < 3) {
      newLevel = 3;
      shouldSendEmail = true;
    } else if (daysPastDue >= config.level2DaysOverdue && ar.dunningLevel < 2) {
      newLevel = 2;
      shouldSendEmail = true;
    } else if (daysPastDue >= config.level1DaysOverdue && ar.dunningLevel < 1) {
      newLevel = 1;
      shouldSendEmail = true;
    }
    
    if (newLevel > ar.dunningLevel) {
      const emailData = generateDunningEmail(newLevel, {
        invoiceId: ar.invoiceId,
        customerName: ar.customerName,
        amountDue: ar.amountDue,
        dueDate: ar.dueDate,
        daysPastDue,
      });
      
      let emailSent = false;
      if (config.autoSendEmails && shouldSendEmail) {
        emailSent = await sendDunningEmail(
          ar.customerEmail,
          emailData.subject,
          emailData.htmlContent,
          emailData.notificationId
        );
      }
      
      // Update AR record
      await prisma.accountsReceivable.update({
        where: { id: ar.id },
        data: {
          dunningLevel: newLevel,
          lastDunningDate: now,
        },
      });
      
      // Log dunning history
      await prisma.dunningHistory.create({
        data: {
          arId: ar.id,
          dunningLevel: newLevel,
          emailSent,
          emailRecipient: ar.customerEmail,
          emailSubject: emailData.subject,
          emailContent: emailData.htmlContent,
        },
      });
      
      // Log agent action
      await logSimpleAction({
        actionType: 'dunning_escalation',
        targetEntity: 'AccountsReceivable',
        targetId: ar.id,
        input: { daysPastDue, previousLevel: ar.dunningLevel, newLevel },
        output: { emailSent, subject: emailData.subject },
        confidence: 1.0,
        anomalyDetected: daysPastDue > 60,
        anomalyType: daysPastDue > 60 ? 'severely_overdue' : undefined,
      });
      
      results.push({
        arId: ar.id,
        invoiceId: ar.invoiceId,
        customerEmail: ar.customerEmail,
        previousLevel: ar.dunningLevel,
        newLevel,
        emailSent,
        action: `Escalated to level ${newLevel}`,
      });
    }
  }
  
  return results;
}

export async function getDunningStats(): Promise<{
  totalOverdue: number;
  byLevel: { level: number; count: number; totalAmount: number }[];
  totalOverdueAmount: number;
  avgDaysOverdue: number;
}> {
  const overdueRecords = await prisma.accountsReceivable.findMany({
    where: { status: 'overdue' },
  });
  
  const byLevel = [0, 1, 2, 3].map(level => {
    const records = overdueRecords.filter((r: any) => r.dunningLevel === level);
    return {
      level,
      count: records.length,
      totalAmount: records.reduce((sum: number, r: any) => sum + r.amountDue, 0),
    };
  });
  
  const totalOverdueAmount = overdueRecords.reduce((sum: number, r: any) => sum + r.amountDue, 0);
  const avgDaysOverdue = overdueRecords.length > 0
    ? overdueRecords.reduce((sum: number, r: any) => sum + r.daysPastDue, 0) / overdueRecords.length
    : 0;
  
  return {
    totalOverdue: overdueRecords.length,
    byLevel,
    totalOverdueAmount,
    avgDaysOverdue,
  };
}

export async function getDunningHistory(arId?: string): Promise<{
  id: string;
  arId: string;
  dunningLevel: number;
  emailSent: boolean;
  emailRecipient: string;
  sentAt: Date;
}[]> {
  return prisma.dunningHistory.findMany({
    where: arId ? { arId } : {},
    orderBy: { sentAt: 'desc' },
    take: 100,
  });
}
