/**
 * Widget data resolver — reports-analytics (wave C).
 *
 * GET /api/analytics/query?widget=<type>&from=&to=&filters=<json>
 * Access: reports:read
 */
import { Hono } from 'hono'
import { z } from 'zod'
import type { AppEnv } from '../../types'
import { authMiddleware } from '../../middleware/auth'
import { requirePermission } from '../../middleware/guards'
import { resolveWidgetData, WIDGET_TYPES } from '@zync/db/queries'
import { withReportCache } from '../../lib/report-cache'

const widgetQuerySchema = z.object({
  widget: z.enum(WIDGET_TYPES),
  from: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
  to: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
  filters: z.string().optional(),
})

const filtersSchema = z.object({
  projectId: z.string().uuid().optional(),
  customerId: z.string().uuid().optional(),
  userId: z.string().uuid().optional(),
  categoryId: z.string().uuid().optional(),
})

function defaultDateRange(): { from: string; to: string } {
  const now = new Date()
  const to = now.toISOString().slice(0, 10)
  const from = new Date(now.getTime() - 29 * 86_400_000).toISOString().slice(0, 10)
  return { from, to }
}

export const analyticsQueryRoutes = new Hono<AppEnv>()

analyticsQueryRoutes.use('*', authMiddleware)
analyticsQueryRoutes.use('*', requirePermission('reports:read'))

analyticsQueryRoutes.get('/query', async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'No tenant context' }, 403)
  }

  const parsed = widgetQuerySchema.safeParse(c.req.query())
  if (!parsed.success) {
    return c.json({ error: 'Invalid query params', details: parsed.error.flatten() }, 400)
  }

  const defaults = defaultDateRange()
  const from = parsed.data.from ?? defaults.from
  const to = parsed.data.to ?? defaults.to
  if (to < from) {
    return c.json({ error: "'to' must be >= 'from'" }, 400)
  }

  let filters: z.infer<typeof filtersSchema> = {}
  if (parsed.data.filters) {
    try {
      const raw = JSON.parse(parsed.data.filters) as unknown
      const fParsed = filtersSchema.safeParse(raw)
      if (!fParsed.success) {
        return c.json({ error: 'Invalid filters JSON', details: fParsed.error.flatten() }, 400)
      }
      filters = fParsed.data
    } catch {
      return c.json({ error: 'Invalid filters JSON' }, 400)
    }
  }

  const tenantId = session.tid
  const widget = parsed.data.widget
  const period = `${from}_${to}_${filters.projectId ?? ''}_${filters.customerId ?? ''}_${filters.userId ?? ''}_${filters.categoryId ?? ''}`
  const db = c.get('db')

  return withReportCache(c.env, tenantId, `widget:${widget}`, period, async () => {
    return resolveWidgetData(
      db,
      {
        CF_ANALYTICS_READ_TOKEN: c.env.CF_ANALYTICS_READ_TOKEN,
        CF_ACCOUNT_ID: c.env.CF_ACCOUNT_ID,
        CF_ANALYTICS_DATASET: c.env.CF_ANALYTICS_DATASET,
      },
      tenantId,
      widget,
      { from, to },
      filters,
    )
  })
})
