/**
 * PATCH /api/user/preferences — dark-light-theme (spec 114).
 *
 * Updates per-(user, tenant) preferences; currently handles ui_theme.
 * Requires an authenticated session (mounted behind authMiddleware).
 *
 * Body (Zod-validated):
 *   { ui_theme?: 'dark' | 'light' | 'system' }
 *
 * Side-effect:
 *   Set-Cookie: ui_theme={value}; Path=/; SameSite=Strict
 *
 * Responses:
 *   200  { ui_theme: 'dark' | 'light' | 'system' }
 *   400  Zod validation error
 *   401  Unauthenticated (authMiddleware)
 *   422  No updatable field supplied
 */
import { Hono } from 'hono'
import { z } from 'zod'
import { createDb, setUserShell, setUserTheme, setUserTimezone } from '@zync/db/queries'
import type { UserId, TenantId } from '@zync/types'
import { isValidTimezone } from '@zync/types'
import type { AppEnv } from '../types'
import { setThemeCookie } from '../lib/theme-cookie'
import { authMiddleware } from '../middleware/auth'

export const updateUserPreferencesSchema = z.object({
  ui_theme: z.enum(['dark', 'light', 'system']).optional(),
  ui_shell: z.enum(['classic', 'os']).optional(),
  timezone: z
    .string()
    .refine(isValidTimezone, { message: 'Invalid IANA timezone' })
    .optional(),
})

export type UpdateUserPreferencesBody = z.infer<typeof updateUserPreferencesSchema>

export const userPreferencesRoute = new Hono<AppEnv>()

// Self-apply authMiddleware so this route is protected regardless of mount site
userPreferencesRoute.use('*', authMiddleware)

userPreferencesRoute.patch('/preferences', async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user') {
    return c.json({ error: 'Unauthorized' }, 401)
  }
  if (!session.tid) {
    return c.json({ error: 'No active tenant' }, 401)
  }

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

  const { ui_theme, ui_shell, timezone } = parsed.data

  if (ui_theme === undefined && ui_shell === undefined && timezone === undefined) {
    return c.json({ error: 'No updatable field supplied' }, 422)
  }

  const db = c.get('db') ?? createDb(c.env)
  const ip = c.req.header('CF-Connecting-IP') ?? null
  const requestId = c.req.header('X-Request-Id') ?? null

  if (ui_theme !== undefined) {
    await setUserTheme(db, {
      userId: session.sub as UserId,
      tenantId: session.tid as TenantId,
      uiTheme: ui_theme,
      actorIp: ip,
      requestId,
    })
    setThemeCookie(c, ui_theme)
  }
  if (ui_shell !== undefined) await setUserShell(db, session.sub as UserId, session.tid as TenantId, ui_shell)

  if (timezone !== undefined) {
    await setUserTimezone(db, session.sub, session.tid, timezone)
  }

  return c.json({ ui_theme: ui_theme ?? null, ui_shell: ui_shell ?? null, timezone: timezone ?? null }, 200)
})
