/**
 * Invoice Draft Library routes — invoice-draft-library (P055).
 * Mounted at /api/invoices/drafts in apps/zync-api/src/routes/index.ts.
 *
 * Routes (relative to mount point /api/invoices/drafts):
 *   GET  /                      → list DRAFT (non-template) invoices
 *   GET  /count                 → count of drafts + templates (for main list pill)
 *   GET  /templates             → list invoice templates
 *   POST /templates             → create new invoice template
 *   GET  /templates/:id         → get single template
 *   DELETE /templates/:id       → delete template
 *   POST /from-template/:id     → create draft invoice from template
 *
 * Notes on scope boundaries:
 * - DELETE /api/invoices/:id (delete a DRAFT) → already handled by core router
 *   (deleteDraftInvoice in queries/invoices.ts). Not duplicated here.
 * - GET /api/invoices?status=DRAFT&is_template=false → handled by core listInvoices
 *   once integrator adds is_template filter to listInvoicesSchema. This router
 *   provides a dedicated /drafts UI endpoint with richer response shape.
 * - The "X drafts" pill count on the main invoice list uses GET /api/invoices/drafts/count.
 */
import { Hono } from 'hono'
import type { AppEnv } from '../../types'
import { authMiddleware } from '../../middleware/auth'
import { requireModuleEnabled } from '../../middleware/require-module-enabled'
import { requirePermission } from '../../middleware/guards'
import {
  listDraftInvoices,
  listDraftsSchema,
  listDraftTemplates as listTemplates,
  listDraftTemplatesSchema as listTemplatesSchema,
  createDraftTemplate as createTemplate,
  createDraftTemplateSchema as createTemplateSchema,
  createInvoiceFromTemplate,
  createFromTemplateSchema,
  countDraftInvoices,
  countDraftTemplates as countTemplates,
  getDraftTemplate as getTemplate,
  deleteDraftTemplate as deleteTemplate,
} from '@zync/db/queries'

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

export const invoiceDraftRoutes = new Hono<AppEnv>()

invoiceDraftRoutes.use('*', authMiddleware)
invoiceDraftRoutes.use('*', requireModuleEnabled('invoices'))

// ── GET /api/invoices/drafts ──────────────────────────────────────────────────
// List DRAFT (non-template) invoices with optional customer search.

invoiceDraftRoutes.get('/', requirePermission('invoices:read'), 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 = listDraftsSchema.safeParse({
    search: query.search,
    page: query.page,
    perPage: query.per_page ?? query.perPage,
  })

  if (!parsed.success) {
    return c.json({ error: 'Validation failed', issues: parsed.error.issues }, 400)
  }

  const db = c.get('db')
  const result = await listDraftInvoices(db, session.tid, parsed.data)
  return c.json(result, 200)
})

// ── GET /api/invoices/drafts/count ────────────────────────────────────────────
// Returns { drafts, templates } for the main invoice list pill.

invoiceDraftRoutes.get('/count', requirePermission('invoices:read'), 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 [drafts, templates] = await Promise.all([
    countDraftInvoices(db, session.tid),
    countTemplates(db, session.tid),
  ])
  return c.json({ drafts, templates }, 200)
})

// ── GET /api/invoices/drafts/templates ────────────────────────────────────────
// List invoice templates.

invoiceDraftRoutes.get('/templates', requirePermission('invoices:read'), 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 = listTemplatesSchema.safeParse({
    page: query.page,
    perPage: query.per_page ?? query.perPage,
  })

  if (!parsed.success) {
    return c.json({ error: 'Validation failed', issues: parsed.error.issues }, 400)
  }

  const db = c.get('db')
  const result = await listTemplates(db, session.tid, parsed.data)
  return c.json(result, 200)
})

// ── POST /api/invoices/drafts/templates ───────────────────────────────────────
// Create a new invoice template (is_template=true, customer_id=NULL).

invoiceDraftRoutes.post('/templates', requirePermission('invoices: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 = createTemplateSchema.safeParse(body)
  if (!parsed.success) {
    return c.json({ error: 'Validation failed', issues: parsed.error.issues }, 400)
  }

  const db = c.get('db')
  const result = await createTemplate(db, session.tid, session.sub, parsed.data)
  return c.json(result, 201)
})

// ── GET /api/invoices/drafts/templates/:id ────────────────────────────────────
// Get a single template by ID.

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

  const id = c.req.param('id')
  const db = c.get('db')
  const template = await getTemplate(db, session.tid, id)

  if (!template) {
    return c.json({ error: 'Template not found' }, 404)
  }
  return c.json(template, 200)
})

// ── DELETE /api/invoices/drafts/templates/:id ─────────────────────────────────
// Delete a template (DRAFT + is_template=true only).

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

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

  try {
    const db = c.get('db')
    await deleteTemplate(db, session.tid, id, session.sub)
    return new Response(null, { status: 204 })
  } catch (err) {
    if (err instanceof Error && err.message.includes('not found')) {
      return c.json({ error: 'Template not found' }, 404)
    }
    if (err instanceof Error && err.message.includes('Only DRAFT')) {
      return c.json({ error: err.message }, 409)
    }
    throw err
  }
})

// ── POST /api/invoices/drafts/from-template/:id ───────────────────────────────
// Create a new DRAFT invoice from a template.
// Returns the new invoice ID and metadata.

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

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

    try {
      const db = c.get('db')
      const result = await createInvoiceFromTemplate(
        db,
        session.tid,
        session.sub,
        templateId,
        parsed.data,
      )
      return c.json(result, 201)
    } catch (err) {
      if (err instanceof Error && err.message.includes('not found')) {
        return c.json({ error: 'Template not found' }, 404)
      }
      throw err
    }
  },
)
