/**
 * Contract expiry-reminder cron — wave-12 (contract-renewal-amendment).
 *
 * POST /api/cron/contract-expiry-reminder
 *
 * Guarded by CRON_SECRET (timing-safe comparison). Runs daily at 08:00 UTC.
 *
 * For each SIGNED contract expiring within 60 days (and not already renewed):
 *   - Creates an in-app notification for the tenant OWNER.
 *   - Fires best-effort (notification failure never fails the cron).
 *
 * Idempotent same-day: notifications are keyed by entityId so duplicates are
 * harmless (insertNotification does not deduplicate, but the UI dedupes by
 * grouping — the cron itself is designed to run once daily).
 */
import { Hono } from 'hono'
import { sql } from '@zync/db'
import { timingSafeEqual } from '@zync/auth'
import {
  createDb,
  getExpiringContracts,
  createNotification,
} from '@zync/db/queries'
import type { AppEnv } from '../../types'

export const contractExpiryReminderRoute = new Hono<AppEnv>()

contractExpiryReminderRoute.post('/', async (c) => {
  // Timing-safe CRON_SECRET check
  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 contracts expiring within 60 days that have not been renewed
  const expiring = await getExpiringContracts(db, 60)

  let notified = 0

  for (const contract of expiring) {
    try {
      // Find the OWNER membership for this tenant (mirrors subscription-trial-check pattern)
      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 = ${contract.tenantId}
              AND r.name = 'OWNER'
              AND tm.status = 'active'
            LIMIT 1`,
      )
      const ownerRow = (result as unknown as { user_id?: string }[])[0]
      const userId = ownerRow?.user_id
      if (!userId) continue

      const daysLeft = Math.ceil(
        (new Date(contract.expiryDate).getTime() - Date.now()) / (1000 * 60 * 60 * 24),
      )

      await createNotification(db, {
        tenantId: contract.tenantId,
        userId,
        type: 'contract_expiry_reminder',
        titleKey: 'notifications.contract_expiry_reminder.title',
        bodyKey: 'notifications.contract_expiry_reminder.body',
        params: {
          contractTitle: contract.title,
          daysLeft,
          contractId: contract.id,
        },
        entityType: 'contract',
        entityId: contract.id,
      })

      notified++
    } catch (err) {
      // Best-effort — never fail the cron for a single contract
      console.error(`[contractExpiryReminder] failed for contract ${contract.id}:`, err)
    }
  }

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