/**
 * Credit-note sub-routes — invoice-credit-notes (wave-12).
 * Mounted on the existing /api/invoices router.
 *
 * Routes:
 *   POST /api/invoices/:id/credit-note      → create DRAFT credit note
 *   GET  /api/invoices/:id/credit-notes     → list credit notes for parent + netInvoiced
 *   POST /api/invoices/:creditNoteId/issue  → issue DRAFT → TAX_ISSUED (assigns CN-#####)
 */
import { Hono } from 'hono'
import type { AppEnv } from '../../types'
import { requirePermission } from '../../middleware/guards'
import {
  createCreditNoteDraft,
  issueCreditNote,
  listCreditNotesForParent,
  createCreditNoteDraftSchema,
  CreditNoteError,
  NotFoundError,
} from '@zync/db/queries'

export const creditNoteRoutes = new Hono<AppEnv>()

// ── POST /api/invoices/:id/credit-note ────────────────────────────────────────
// Create a DRAFT credit note for the parent invoice.

creditNoteRoutes.post('/:id/credit-note', requirePermission('invoices:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const parentId = c.req.param('id')
  const body = await c.req.json().catch(() => null)
  const parsed = createCreditNoteDraftSchema.safeParse(body)
  if (!parsed.success) {
    return c.json({ error: 'Validation failed', issues: parsed.error.issues }, 400)
  }

  const db = c.get('db')

  try {
    const creditNote = await createCreditNoteDraft(
      db,
      session.tid,
      parentId,
      session.sub,
      parsed.data,
    )
    return c.json(creditNote, 201)
  } catch (err) {
    if (err instanceof NotFoundError) {
      return c.json({ error: 'Not found' }, 404)
    }
    if (err instanceof CreditNoteError) {
      if (err.code === 'DUPLICATE_DRAFT') {
        return c.json({ error: { code: err.code, message: err.message } }, 409)
      }
      return c.json({ error: { code: err.code, message: err.message } }, 422)
    }
    throw err
  }
})

// ── GET /api/invoices/:id/credit-notes ────────────────────────────────────────
// List credit notes for a parent invoice + netInvoiced.

creditNoteRoutes.get('/:id/credit-notes', requirePermission('invoices:read'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const parentId = c.req.param('id')
  const db = c.get('db')

  try {
    const result = await listCreditNotesForParent(db, session.tid, parentId)
    return c.json(result, 200)
  } catch (err) {
    if (err instanceof NotFoundError) {
      return c.json({ error: 'Not found' }, 404)
    }
    throw err
  }
})

// ── POST /api/invoices/:creditNoteId/issue ────────────────────────────────────
// Issue a DRAFT credit note: assigns CN-##### number, sets TAX_ISSUED.

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

  const creditNoteId = c.req.param('creditNoteId')
  const db = c.get('db')

  try {
    const issued = await issueCreditNote(db, session.tid, creditNoteId, session.sub)

    // Enqueue adapter push if a QUEUE binding is available (fire-and-forget)
    try {
      await c.env.QUEUE.send({ type: 'invoice.push', invoiceId: creditNoteId, tenantId: session.tid })
    } catch {
      // No adapter configured or queue unavailable — not fatal
    }

    return c.json(issued, 200)
  } catch (err) {
    if (err instanceof NotFoundError) {
      return c.json({ error: 'Not found' }, 404)
    }
    if (err instanceof CreditNoteError) {
      return c.json({ error: { code: err.code, message: err.message } }, 422)
    }
    throw err
  }
})
