/**
 * Recurring-invoice generation core — recurring-invoices (P061).
 *
 * Single source of truth for the daily generation loop. Invoked by BOTH:
 *   - the HTTP route POST /api/cron/recurring-invoice-generator (CRON_SECRET-gated)
 *   - RecurringInvoiceAlarmDO.alarm() (self-rescheduling Durable Object alarm)
 *
 * Pure orchestration over @zync/db/queries — no auth, no HTTP, no scheduling.
 *
 * Algorithm (per spec §"Generation Mechanism"):
 *   1. Query templates due today (status='active', next_generation_date <= today,
 *      end_date IS NULL OR end_date >= today).
 *   2. For each template: resolve tenant country, generateInvoiceFromTemplate
 *      (idempotency-guarded internally), auto-send if configured, notify the
 *      tenant owner when the schedule completes.
 *   3. Per-template errors are caught so one failure never aborts the run.
 */
import {
  listDueRecurringTemplates,
  generateInvoiceFromTemplate,
  sendInvoice,
  createNotification,
  getTenantById,
  getTenantOwnerUserId,
  type Db,
} from '@zync/db/queries'
import type { TenantId } from '@zync/types'

export interface RecurringGenerationSummary {
  processed: number
  generated: number
  skipped: number
  errors: number
}

async function notifyTenantOwner(
  db: Db,
  tenantId: string,
  templateTitle: string,
  templateId: string,
): Promise<void> {
  try {
    const ownerUserId = await getTenantOwnerUserId(db, tenantId)
    if (!ownerUserId) return

    await createNotification(db, {
      tenantId,
      userId: ownerUserId,
      type: 'recurring_invoice_completed',
      titleKey: 'notifications.recurring_invoice_completed.title',
      bodyKey: 'notifications.recurring_invoice_completed.body',
      params: { templateTitle, templateId },
      entityType: 'recurring_invoice_template',
      entityId: templateId,
    })
  } catch (err) {
    console.error(`[recurringInvoiceGenerator] notifyTenantOwner error: ${err}`)
  }
}

export async function runRecurringInvoiceGeneration(
  db: Db,
  today: string,
): Promise<RecurringGenerationSummary> {
  const dueTemplates = await listDueRecurringTemplates(db, today)

  let generated = 0
  let skipped = 0
  let errors = 0

  for (const template of dueTemplates) {
    try {
      const tenant = await getTenantById(db, template.tenantId as TenantId)
      const countryCode = tenant?.countryCode ?? 'IL'

      const result = await generateInvoiceFromTemplate(
        db,
        template,
        template.createdBy,
        countryCode,
      )

      if (result.skipped) {
        skipped++
        console.log(
          `[recurringInvoiceGenerator] skipped templateId=${template.id} period=${template.nextGenerationDate}`,
        )
        continue
      }

      if (template.autoSend && result.invoiceId) {
        try {
          await sendInvoice(
            db,
            template.tenantId,
            result.invoiceId,
            template.createdBy,
            countryCode,
            template.nextGenerationDate,
          )
        } catch (sendErr) {
          console.error(
            `[recurringInvoiceGenerator] auto-send failed invoiceId=${result.invoiceId} templateId=${template.id}: ${sendErr}`,
          )
        }
      }

      if (result.completed) {
        await notifyTenantOwner(db, template.tenantId, template.title, template.id)
      }

      generated++
      console.log(
        `[recurringInvoiceGenerator] generated invoiceId=${result.invoiceId} templateId=${template.id} period=${template.nextGenerationDate}`,
      )
    } catch (err) {
      errors++
      console.error(
        `[recurringInvoiceGenerator] error for templateId=${template.id}: ${err}`,
      )
    }
  }

  return {
    processed: dueTemplates.length,
    generated,
    skipped,
    errors,
  }
}
