/**
 * Audit partition create cron — audit-compliance (wave-11 leaf-D).
 * Invoked on the 1st of each month at 01:00 UTC via the cron dispatcher.
 * Creates the next month's audit_log partition so inserts never fail.
 *
 * Guarded by CRON_SECRET (timing-safe comparison via @zync/auth#timingSafeEqual).
 */
import { Hono } from 'hono'
import { timingSafeEqual } from '@zync/auth'
import { sql } from '@zync/db'
import type { AppEnv } from '../../types'
import { createDb } from '@zync/db/queries'

export const auditPartitionCreateCron = new Hono<AppEnv>()

auditPartitionCreateCron.post('/', async (c) => {
  // Timing-safe secret check — never use ===
  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: 'Forbidden' }, 403)
  }

  const db = createDb(c.env)

  // Determine the next month from current date
  const now = new Date()
  const nextMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1))
  const monthAfter = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 2, 1))

  const partitionName = `audit_log_${nextMonth.getUTCFullYear()}_${String(nextMonth.getUTCMonth() + 1).padStart(2, '0')}`
  const fromDate = nextMonth.toISOString().slice(0, 10)
  const toDate = monthAfter.toISOString().slice(0, 10)

  // sql.raw is safe here: partitionName is derived from server-computed Date arithmetic
  // (not user input), and fromDate/toDate are ISO date strings from toISOString().slice(0,10).
  // DDL CREATE TABLE cannot use parameterized placeholders in PostgreSQL.
  await db.execute(
    sql.raw(
      `CREATE TABLE IF NOT EXISTS ${partitionName} PARTITION OF audit_log FOR VALUES FROM ('${fromDate}') TO ('${toDate}')`,
    ),
  )

  return c.json({ ok: true, partition: partitionName, from: fromDate, to: toDate }, 200)
})
