/**
 * Lead re-engagement cron — wave-14 (lead-lost-re-engagement).
 *
 * POST /api/cron/lead-reengagement
 *
 * Guarded by CRON_SECRET (timing-safe comparison). Runs daily at 10:00 UTC.
 *
 * For each LOST lead where reengagement_at <= now() AND reengagement_notified_at IS NULL:
 *   - Creates an in-app notification for the assigned user (or tenant OWNER as fallback).
 *   - Stamps reengagement_notified_at = now() so the cron never re-fires for the same lead.
 *   - Failures are isolated per-lead; one failure never blocks the rest.
 */
import { Hono } from 'hono'
import { sql } from '@zync/db'
import { timingSafeEqual } from '@zync/auth'
import {
  createDb,
  selectDueReengagementLeads,
  markReengagementNotified,
  createNotification,
} from '@zync/db/queries'
import type { AppEnv } from '../../types'

export const leadReengagementCronRoute = new Hono<AppEnv>()

leadReengagementCronRoute.post('/', async (c) => {
  // Fail-closed: reject when secret not configured
  const expected = c.env.CRON_SECRET
  if (!expected || expected.length < 16) {
    return c.json({ error: 'Server misconfigured' }, 500)
  }
  const secret = c.req.header('x-cron-secret') ?? ''
  if (!timingSafeEqual(secret, expected)) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const db = createDb(c.env)
  const now = new Date()

  const dueleads = await selectDueReengagementLeads(db, now)

  let notified = 0

  for (const lead of dueleads) {
    try {
      // Prefer the assigned user; fall back to tenant OWNER
      let userId: string | undefined = lead.assignedTo ?? undefined

      if (!userId) {
        const result = await db.execute(
          sql`SELECT tm.user_id
              FROM tenant_memberships tm
              JOIN roles r ON r.id = tm.role_id
              WHERE tm.tenant_id = ${lead.tenantId}
                AND r.name = 'OWNER'
                AND tm.status = 'active'
              LIMIT 1`,
        )
        const ownerRow = (result as unknown as { user_id?: string }[])[0]
        userId = ownerRow?.user_id
      }

      if (!userId) {
        // No user to notify; still stamp as notified to avoid infinite retries
        await markReengagementNotified(db, lead.id, lead.tenantId, now)
        continue
      }

      await createNotification(db, {
        tenantId: lead.tenantId,
        userId,
        type: 'lead_reengagement_due',
        titleKey: 'notifications.lead_reengagement_due.title',
        bodyKey: 'notifications.lead_reengagement_due.body',
        params: {
          leadName: lead.name,
          leadId: lead.id,
        },
        entityType: 'lead',
        entityId: lead.id,
      })

      // Stamp AFTER successful notification to preserve delivery guarantee
      await markReengagementNotified(db, lead.id, lead.tenantId, now)
      notified++
    } catch (err) {
      // Best-effort — never fail the cron for a single lead
      console.error(`[leadReengagement] failed for lead ${lead.id}:`, err)
    }
  }

  return c.json({ ok: true, checked: dueleads.length, notified }, 200)
})
