/**
 * Invoice reminder send service — invoice-payment-reminders (wave-13).
 *
 * Resolves the recipient, builds the email content, sends via @zync/notifications,
 * and advances the per-invoice reminder state.
 *
 * Dunning dedup guard: post-due stages (offset_days > 0) are suppressed when
 * the tenant has any dunning_schedules row (dunning is handling overdue outreach).
 */
import {
  computeNextReminder,
  parseReminderSchedule,
  advanceInvoiceReminder,
  getTenantReminderSettings,
  resolveReminderRecipient,
  type ReminderDueInvoice,
} from '@zync/db/queries'
import { listDunningSchedules } from '@zync/db/queries'
import { sendEmail } from '@zync/notifications'
import type { Db } from '@zync/db'
import type { Env } from '@zync/types'

// Reminder subject line per stage offset_days
function reminderSubject(invoiceRef: string, offsetDays: number): string {
  if (offsetDays < 0) {
    const absDays = Math.abs(offsetDays)
    return `Invoice due in ${absDays} day${absDays !== 1 ? 's' : ''} — ${invoiceRef}`
  }
  if (offsetDays === 0) {
    return `Invoice due today — ${invoiceRef}`
  }
  if (offsetDays === 30) {
    return `Final notice: Invoice overdue — ${invoiceRef}`
  }
  if (offsetDays === 14) {
    return `Follow-up: Invoice overdue — ${invoiceRef}`
  }
  return `Invoice overdue — ${invoiceRef}`
}

export interface SendReminderResult {
  sent: boolean
  skipped?: string
  recipient?: string
}

/**
 * Send a single invoice reminder and advance its state.
 * Returns whether the email was sent or skipped (with reason).
 */
export async function sendInvoiceReminder(
  db: Db,
  env: Env,
  invoice: ReminderDueInvoice,
  opts?: { manualSend?: boolean },
): Promise<SendReminderResult> {
  const tenantId = invoice.tenantId

  // Resolve recipient
  if (!invoice.customerId) {
    return { sent: false, skipped: 'no_customer' }
  }
  const recipientEmail = await resolveReminderRecipient(db, tenantId, invoice.customerId)
  if (!recipientEmail) {
    return { sent: false, skipped: 'no_recipient_email' }
  }

  // Dunning dedup guard: suppress post-due stages when dunning is configured
  const offsetDays = invoice.nextReminderOffset ?? 0
  if (!opts?.manualSend && offsetDays > 0) {
    const dunningSchedules = await listDunningSchedules(db, tenantId)
    if (dunningSchedules.length > 0) {
      // Dunning is active — skip post-due reminder
      const tenantSettings = await getTenantReminderSettings(db, tenantId)
      const schedule = parseReminderSchedule(tenantSettings.schedule)
      const dueDate = invoice.dueDate ? new Date(invoice.dueDate) : null
      const next = dueDate
        ? computeNextReminder(dueDate, schedule, offsetDays)
        : null
      await advanceInvoiceReminder(db, invoice.id, tenantId, next)
      return { sent: false, skipped: 'dunning_active' }
    }
  }

  const invoiceRef =
    invoice.invoiceNumber ?? invoice.proformaNumber ?? invoice.id

  const subject = reminderSubject(invoiceRef, offsetDays)

  const bodyHe = `חשבונית ${invoiceRef} ממתינה לתשלום.\n\nסכום לתשלום: ${invoice.currency} ${invoice.total}.\n\nאנא בצע את התשלום בהקדם.`

  // Send Hebrew locale by default (IL-first)
  await sendEmail(
    {
      to: recipientEmail,
      templateKey: 'invoice_reminder',
      locale: 'he-IL',
      vars: {
        subject,
        title: subject,
        body: bodyHe,
        invoiceRef,
        amount: invoice.total,
        currency: invoice.currency,
      },
    },
    env,
  )

  // Advance to next reminder stage
  const dueDate = invoice.dueDate ? new Date(invoice.dueDate) : null
  const tenantSettings = await getTenantReminderSettings(db, tenantId)
  const schedule = parseReminderSchedule(tenantSettings.schedule)
  const next = dueDate ? computeNextReminder(dueDate, schedule, offsetDays) : null
  await advanceInvoiceReminder(db, invoice.id, tenantId, next)

  return { sent: true, recipient: recipientEmail }
}
