/**
 * requireModuleEnabled — API middleware factory (module-management spec, Task 13).
 *
 * Wraps a module's routes. Returns `403 { error:'module_disabled', module }` when
 * the tenant has the module disabled. 'system' is always allowed without a DB query.
 *
 * Per-request cache: the enabled set is computed once per request and stored on
 * the Hono context so multiple guarded routes in one request do not re-query.
 *
 * Mount AFTER auth middleware (needs a populated session).
 */
import type { MiddlewareHandler } from 'hono'
import type { AppEnv } from '../types'
import { getEnabledModuleIds } from '@zync/db/queries'
import type { ModuleId } from '@zync/modules'
import type { SessionPayload } from '@zync/types'

/** Key used to cache the per-request enabled module set on the Hono context. */
const CACHE_KEY = '__enabledModuleIds__' as const

/**
 * Returns a Hono middleware that guards a route behind a module-enabled check.
 * Called by every downstream module's routes as the canonical 403 shape.
 */
export function requireModuleEnabled(moduleId: ModuleId): MiddlewareHandler<AppEnv> {
  return async (c, next) => {
    // 'system' is always-on — skip all DB work
    if (moduleId === 'system') {
      await next()
      return
    }

    const session = c.get('session') as SessionPayload | undefined
    if (!session || session.type !== 'user' || !session.tid) {
      return c.json({ error: 'Unauthorized' }, 401)
    }

    const db = c.get('db')
    const tenantId = session.tid

    // Per-request cache: reuse enabledIds across multiple guarded routes
    let enabledIds = (c as unknown as Record<string, unknown>)[CACHE_KEY] as
      | ModuleId[]
      | undefined

    if (!enabledIds) {
      enabledIds = await getEnabledModuleIds(db, tenantId)
      ;(c as unknown as Record<string, unknown>)[CACHE_KEY] = enabledIds
    }

    if (!enabledIds.includes(moduleId)) {
      return c.json({ error: 'module_disabled', module: moduleId }, 403)
    }

    await next()
  }
}

// Re-export the ModuleId type for downstream module consumers
export type { ModuleId }
