/**
 * Report + analytics response caching — reports-analytics (wave C).
 *
 * Cache key: `{tenantId}:{reportType}:{period}:v{financials_version}`
 * Version counter in KV (`financials_version:{tenantId}`), bumped on invoice/expense writes.
 */
import type { Env } from '@zync/types'

const CACHE_TTL_SECONDS = 300 // 5 minutes per spec

function financialsVersionKey(tenantId: string): string {
  return `financials_version:${tenantId}`
}

export async function getFinancialsVersion(kv: KVNamespace, tenantId: string): Promise<number> {
  const raw = await kv.get(financialsVersionKey(tenantId))
  const version = raw ? Number(raw) : 0
  return Number.isFinite(version) ? version : 0
}

export function reportCacheKey(
  tenantId: string,
  reportType: string,
  period: string,
  version: number,
): string {
  return `${tenantId}:${reportType}:${period}:v${version}`
}

function cacheRequestForKey(key: string): Request {
  return new Request(`https://zync-internal/report-cache/${encodeURIComponent(key)}`)
}

/**
 * Wrap a JSON producer in cache.default with 5-minute TTL.
 * Returns a Response (caller can return directly from Hono handler).
 */
export async function withReportCache<T>(
  env: Env,
  tenantId: string,
  reportType: string,
  period: string,
  producer: () => Promise<T>,
): Promise<Response> {
  const version = await getFinancialsVersion(env.KV, tenantId)
  const key = reportCacheKey(tenantId, reportType, period, version)
  const cacheKey = cacheRequestForKey(key)
  const cache = caches.default

  const hit = await cache.match(cacheKey)
  if (hit) return hit

  const data = await producer()
  const response = new Response(JSON.stringify(data), {
    status: 200,
    headers: {
      'Content-Type': 'application/json',
      'Cache-Control': `max-age=${CACHE_TTL_SECONDS}`,
    },
  })

  await cache.put(cacheKey, response.clone())
  return response
}

/** Increment per-tenant financials version after invoice/expense writes. */
export async function bumpFinancialsVersion(env: Env, tenantId: string): Promise<void> {
  const kvKey = financialsVersionKey(tenantId)
  const raw = await env.KV.get(kvKey)
  const current = raw ? Number(raw) : 0
  const next = (Number.isFinite(current) ? current : 0) + 1
  await env.KV.put(kvKey, String(next))
}
