/**
 * nii-advances.ts — NII advance payments CRUD routes.
 * Spec: 2026-06-01-bituach-leumi (spec 175, wave-15)
 *
 * Mounted at /api/nii-advances in the main routes index.
 *
 * Routes:
 *   GET    /               ?year   reports:read   → list advance payments
 *   POST   /               body    reports:write  → create advance payment
 *   PATCH  /:id            body    reports:write  → update advance payment
 *   DELETE /:id                    reports:write  → delete advance payment
 */
import { Hono } from 'hono'
import { z } from 'zod'
import {
  createDb,
  listNiiAdvances,
  createNiiAdvance,
  updateNiiAdvance,
  deleteNiiAdvance,
} from '@zync/db/queries'
import type { AppEnv } from '../types'
import { authMiddleware } from '../middleware/auth'
import { requirePermission } from '../middleware/guards'

// ── Zod schemas ───────────────────────────────────────────────────────────────

const listQuerySchema = z.object({
  year: z
    .string()
    .regex(/^\d{4}$/, 'year must be a 4-digit integer')
    .transform((s) => parseInt(s, 10)),
})

const createBodySchema = z.object({
  year: z.number().int().min(2000).max(2100),
  month: z.number().int().min(1).max(12),
  amount: z.number().positive(),
  paid_at: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'paid_at must be YYYY-MM-DD'),
  notes: z.string().optional(),
})

const patchBodySchema = z.object({
  amount: z.number().positive().optional(),
  paid_at: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'paid_at must be YYYY-MM-DD').optional(),
  notes: z.string().optional(),
})

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

export const niiAdvancesRoutes = new Hono<AppEnv>()
niiAdvancesRoutes.use('*', authMiddleware)

// ── GET / — list advances for year ───────────────────────────────────────────

niiAdvancesRoutes.get('/', requirePermission('reports:read'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid || !session.sub) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const url = new URL(c.req.url)
  const raw = Object.fromEntries(url.searchParams.entries())
  const parsed = listQuerySchema.safeParse(raw)
  if (!parsed.success) {
    return c.json({ error: 'Invalid query', issues: parsed.error.issues }, 400)
  }

  const db = createDb(c.env)
  const advances = await listNiiAdvances(db, session.tid, session.sub, parsed.data.year)
  return c.json(advances, 200)
})

// ── POST / — create advance payment ──────────────────────────────────────────

niiAdvancesRoutes.post('/', requirePermission('reports:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid || !session.sub) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

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

  const db = createDb(c.env)

  try {
    const advance = await createNiiAdvance(db, session.tid, session.sub, {
      year: parsed.data.year,
      month: parsed.data.month,
      amount: parsed.data.amount,
      paidAt: parsed.data.paid_at,
      notes: parsed.data.notes,
    })
    return c.json(advance, 201)
  } catch (err) {
    // Unique constraint: one advance per tenant/user/year/month
    if (err instanceof Error && err.message.includes('unique')) {
      return c.json(
        { error: 'Advance payment already recorded for this month. Use PATCH to update.' },
        409,
      )
    }
    throw err
  }
})

// ── PATCH /:id — update advance payment ──────────────────────────────────────

niiAdvancesRoutes.patch('/:id', requirePermission('reports:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid || !session.sub) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const id = c.req.param('id')

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

  const db = createDb(c.env)
  const updated = await updateNiiAdvance(db, session.tid, session.sub, id, {
    amount: parsed.data.amount,
    paidAt: parsed.data.paid_at,
    notes: parsed.data.notes,
  })

  if (!updated) {
    return c.json({ error: 'Not found' }, 404)
  }

  return c.json(updated, 200)
})

// ── DELETE /:id — delete advance payment ─────────────────────────────────────

niiAdvancesRoutes.delete('/:id', requirePermission('reports:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid || !session.sub) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const id = c.req.param('id')
  const db = createDb(c.env)
  const deleted = await deleteNiiAdvance(db, session.tid, session.sub, id)

  if (!deleted) {
    return c.json({ error: 'Not found' }, 404)
  }

  return c.json({ success: true }, 200)
})
