/**
 * Currency / exchange-rate routes — multi-currency (wave-10, leaf-4).
 * Mounted at /api/currencies in apps/zync-api/src/routes/index.ts.
 *
 * Routes:
 *   GET  /rates              → list all configured exchange rates
 *   POST /rates              → upsert a rate (admin/staff)
 *   GET  /convert            → convert amount between currencies
 */
import { Hono } from 'hono'
import { z } from 'zod'
import type { AppEnv } from '../../types'
import { authMiddleware } from '../../middleware/auth'
import { requirePermission } from '../../middleware/guards'
import {
  getExchangeRate,
  upsertExchangeRate,
  convertAmount,
  listExchangeRates,
} from '@zync/db/queries'

// ── Validation schemas ─────────────────────────────────────────────────────────

const UpsertRateBodySchema = z.object({
  from: z.string().length(3).toUpperCase(),
  to: z.string().length(3).toUpperCase(),
  rate: z.string().regex(/^\d+(\.\d+)?$/, 'rate must be a positive numeric string'),
  date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'date must be YYYY-MM-DD'),
  source: z.enum(['manual', 'boi']).default('manual'),
})

const ConvertQuerySchema = z.object({
  from: z.string().length(3),
  to: z.string().length(3),
  amount: z.string().regex(/^\d+(\.\d+)?$/),
  date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
})

// ── Router ─────────────────────────────────────────────────────────────────────

export const currencyRoutes = new Hono<AppEnv>()

currencyRoutes.use('*', authMiddleware)

/**
 * GET /currencies/rates
 * Returns all configured exchange rates for the authenticated tenant.
 */
currencyRoutes.get('/rates', async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const rates = await listExchangeRates(db, session.tid)
  return c.json({ rates })
})

/**
 * POST /currencies/rates
 * Upsert an exchange rate for a currency pair on a date.
 * Requires settings:write permission (admins/owners only).
 */
currencyRoutes.post('/rates', requirePermission('settings:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)

  const body = await c.req.json().catch(() => null)
  const parsed = UpsertRateBodySchema.safeParse(body)
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.flatten() }, 400)
  }

  const db = c.get('db')
  const { from, to, rate, date, source } = parsed.data

  const row = await upsertExchangeRate(db, session.tid, session.sub, from, to, rate, date, source)
  return c.json({ rate: row }, 201)
})

/**
 * GET /currencies/convert?from=ILS&to=USD&amount=1000&date=2024-01-01
 * Returns the converted amount using the tenant's stored exchange rate.
 */
currencyRoutes.get('/convert', async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)

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

  const db = c.get('db')
  const { from, to, amount, date } = parsed.data

  const converted = await convertAmount(db, session.tid, amount, from.toUpperCase(), to.toUpperCase(), date)
  if (converted === null) {
    const rateRow = await getExchangeRate(db, session.tid, from.toUpperCase(), to.toUpperCase(), date)
    if (!rateRow) {
      return c.json(
        { error: `No exchange rate configured for ${from.toUpperCase()} → ${to.toUpperCase()}` },
        404,
      )
    }
  }

  return c.json({ from: from.toUpperCase(), to: to.toUpperCase(), amount, converted, date })
})
