/**
 * Invoice-scoped receipt issue routes — invoice-receipt-document (wave-12, spec 179).
 * Mounted separately at /api/invoices in routes/index.ts (same pattern as payments.ts).
 * Applies authMiddleware locally — session is required for requirePermission.
 *
 * Routes:
 *   POST /api/invoices/:id/receipts          → issue standalone קבלה (doc_type='receipt')
 *   POST /api/invoices/:id/invoice-receipt   → issue חשבונית מס/קבלה (doc_type='invoice_receipt')
 */
import { Hono } from 'hono'
import type { Context } from 'hono'
import type { AppEnv } from '../../types'
import { authMiddleware } from '../../middleware/auth'
import { bumpFinancialsVersionOnWrite } from '../../middleware/bump-financials-version'
import { requirePermission } from '../../middleware/guards'
import {
  issueStandaloneReceipt,
  issueInvoiceReceipt,
  issueStandaloneReceiptSchema,
  issueInvoiceReceiptSchema,
  ReceiptNotFoundError,
  ReceiptConflictError,
} from '@zync/db/queries'
import type { ReceiptObject } from '@zync/types'
import { generateAndStoreReceiptSnapshot } from '../../lib/receipt-snapshot'
import { generateAndStoreInvoiceSnapshot } from '../../lib/invoice-snapshot'
import { sendReceiptIssuedEmail } from '../../services/receipt-issued-email'

function enqueueReceiptIssuedEmail(
  c: Context<AppEnv>,
  tenantId: string,
  receipt: ReceiptObject,
): void {
  c.executionCtx.waitUntil(
    sendReceiptIssuedEmail(c.get('db'), c.env, tenantId, receipt).catch((err) => {
      console.error('[issue-receipt] customer email failed:', err)
    }),
  )
}

function getTenantCountry(c: Context<AppEnv>): string {
  const session = c.get('session')
  if (session && 'countryCode' in session && typeof session.countryCode === 'string') {
    return session.countryCode
  }
  return 'IL'
}

export const invoiceReceiptIssueRoutes = new Hono<AppEnv>()

invoiceReceiptIssueRoutes.use('*', authMiddleware)
invoiceReceiptIssueRoutes.use('*', bumpFinancialsVersionOnWrite)

// ── POST /api/invoices/:id/receipts ───────────────────────────────────────────

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

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

    const db = c.get('db')
    try {
      const receipt = await issueStandaloneReceipt(db, session.tid, session.sub, invoiceId, parsed.data)
      try {
        await generateAndStoreReceiptSnapshot(
          { db, env: c.env, executionCtx: c.executionCtx },
          session.tid,
          receipt.id,
        )
      } catch (snapshotErr) {
        console.error(
          '[issue-receipt] snapshot failed (receipt issued; retry GET /pdf to backfill):',
          snapshotErr,
        )
      }
      enqueueReceiptIssuedEmail(c, session.tid, receipt)
      return c.json(receipt, 201)
    } catch (err) {
      if (err instanceof ReceiptNotFoundError) {
        return c.json({ error: 'Not found' }, 404)
      }
      if (err instanceof ReceiptConflictError) {
        return c.json({ error: err.message }, 409)
      }
      throw err
    }
  },
)

// ── POST /api/invoices/:id/invoice-receipt ────────────────────────────────────

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

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

    const db = c.get('db')
    const countryCode = getTenantCountry(c)
    try {
      const { receipt, taxIssued } = await issueInvoiceReceipt(
        db,
        session.tid,
        session.sub,
        invoiceId,
        parsed.data,
        countryCode,
      )
      try {
        await generateAndStoreReceiptSnapshot(
          { db, env: c.env, executionCtx: c.executionCtx },
          session.tid,
          receipt.id,
        )
      } catch (snapshotErr) {
        console.error(
          '[issue-invoice-receipt] receipt snapshot failed (receipt issued; retry GET /pdf to backfill):',
          snapshotErr,
        )
      }
      if (taxIssued) {
        try {
          await generateAndStoreInvoiceSnapshot(
            { db, env: c.env, executionCtx: c.executionCtx },
            session.tid,
            invoiceId,
          )
        } catch (snapshotErr) {
          console.error(
            '[issue-invoice-receipt] invoice snapshot failed (invoice issued; retry issue-tax to backfill):',
            snapshotErr,
          )
        }
      }
      enqueueReceiptIssuedEmail(c, session.tid, receipt)
      return c.json(receipt, 201)
    } catch (err) {
      if (err instanceof ReceiptNotFoundError) {
        return c.json({ error: 'Not found' }, 404)
      }
      if (err instanceof ReceiptConflictError) {
        return c.json({ error: err.message }, 409)
      }
      throw err
    }
  },
)
