/**
 * Recurring expense generator cron — recurring-expenses (wave-10 leaf3).
 *
 * POST /api/cron/generate-recurring-expenses
 *
 * Guarded by CRON_SECRET (timing-safe comparison).
 * Recommended schedule: `0 7 * * *` (daily at 07:00 UTC).
 *
 * Algorithm:
 *   1. Query all tenants with active recurring_expense_templates due today or earlier.
 *   2. For each due template: create an expense record, advance nextDueAt.
 *   3. Per-tenant errors are caught so one failure does not abort the run.
 */
import { Hono } from 'hono'
import { timingSafeEqual } from '@zync/auth'
import {
  createDb,
  generateDueExpenses,
} from '@zync/db/queries'
import type { AppEnv } from '../../types'
import { sql } from '@zync/db'

export const recurringExpenseGeneratorCron = new Hono<AppEnv>()

recurringExpenseGeneratorCron.post('/', async (c) => {
  // ── CRON_SECRET guard ────────────────────────────────────────────────────────
  const secret = c.req.header('x-cron-secret') ?? ''
  const expected = c.env.CRON_SECRET
  if (!expected || expected.length < 16) {
    return c.json({ error: 'Server misconfigured' }, 500)
  }

  if (!timingSafeEqual(secret, expected)) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const db = createDb(c.env)

  // Get all tenant IDs with active due templates
  const result = await db.execute<{ tenant_id: string }>(sql`
    SELECT DISTINCT tenant_id
    FROM recurring_expense_templates
    WHERE is_active = true
      AND next_due_at <= NOW()
  `)

  const tenantIds = (result as unknown as { tenant_id: string }[]).map((r) => r.tenant_id)

  let totalGenerated = 0
  let totalErrors = 0

  for (const tenantId of tenantIds) {
    try {
      const summary = await generateDueExpenses(db, tenantId)
      totalGenerated += summary.generated
      totalErrors += summary.errors
    } catch {
      totalErrors++
    }
  }

  return c.json({
    tenantsProcessed: tenantIds.length,
    totalGenerated,
    totalErrors,
    runAt: new Date().toISOString(),
  })
})
