/**
 * Public API app router — zapier-make-integration (wave-13).
 * Mounts all /v1/* route handlers.
 *
 * This module exports `PublicApiContext` (shared request context) and
 * `handlePublicApiRequest` (the main dispatch function).
 *
 * Auth middleware (tier gate + scope check) is expected to run BEFORE
 * calling these route handlers. Each handler receives a pre-validated ctx.
 */
import type { Db } from '@zync/db'

export interface PublicApiContext {
  request: Request
  db: Db
  tenantId: string
  /** Resolved scopes for the authenticated token (API key or OAuth). */
  scopes: string[]
  /** User ID resolved from OAuth token (null for API key auth). */
  userId: string | null
  /** OAuth client ID that minted the bearer token (null for API key auth). */
  oauthClientId: string | null
}

// Route imports
import { listLeads, createLead, updateLeadStage } from './routes/leads'
import { createTimeEntry } from './routes/time'
import { sendInvoice } from './routes/invoice-send'
import {
  searchCustomersByEmail,
  searchProjectsByName,
  searchInvoicesByNumber,
  listCustomers,
  listProjects,
  listInvoices,
  listTasks,
} from './routes/search'
import {
  subscribeWebhook,
  unsubscribeWebhook,
  listWebhooks,
} from './routes/webhooks'

/**
 * Dispatch a validated public-API request to the appropriate route handler.
 * Returns null if no route matched (caller should 404).
 */
export async function handlePublicApiRequest(
  ctx: PublicApiContext,
): Promise<Response | null> {
  const url = new URL(ctx.request.url)
  const { method, pathname } = { method: ctx.request.method, pathname: url.pathname }

  // Normalize path: strip /v1 prefix if present
  const path = pathname.replace(/^\/v1/, '')

  // ── /leads ────────────────────────────────────────────────────────────────
  if (method === 'GET' && path === '/leads') {
    return listLeads(ctx)
  }
  if (method === 'POST' && path === '/leads') {
    return createLead(ctx)
  }
  const leadIdMatch = path.match(/^\/leads\/([^/]+)$/)
  if (method === 'PATCH' && leadIdMatch) {
    return updateLeadStage(ctx, leadIdMatch[1]!)
  }

  // ── /time ─────────────────────────────────────────────────────────────────
  if (method === 'POST' && path === '/time') {
    return createTimeEntry(ctx)
  }

  // ── /invoices/:id/send ────────────────────────────────────────────────────
  const invoiceSendMatch = path.match(/^\/invoices\/([^/]+)\/send$/)
  if (method === 'POST' && invoiceSendMatch) {
    return sendInvoice(ctx, invoiceSendMatch[1]!)
  }

  // ── /webhooks ─────────────────────────────────────────────────────────────
  if (method === 'GET' && path === '/webhooks') {
    return listWebhooks(ctx)
  }
  if (method === 'POST' && path === '/webhooks') {
    return subscribeWebhook(ctx)
  }
  const webhookIdMatch = path.match(/^\/webhooks\/([^/]+)$/)
  if (method === 'DELETE' && webhookIdMatch) {
    return unsubscribeWebhook(ctx, webhookIdMatch[1]!)
  }

  // ── /customers (search extension) ────────────────────────────────────────
  if (method === 'GET' && path === '/customers') {
    const email = url.searchParams.get('email')
    if (email) {
      return searchCustomersByEmail(ctx, email)
    }
    return listCustomers(ctx)
  }

  // ── /projects (search extension) ─────────────────────────────────────────
  if (method === 'GET' && path === '/projects') {
    const name = url.searchParams.get('name')
    if (name) {
      return searchProjectsByName(ctx, name)
    }
    return listProjects(ctx)
  }

  // ── /invoices (search extension) ─────────────────────────────────────────
  if (method === 'GET' && path === '/invoices') {
    const number = url.searchParams.get('number')
    if (number) {
      return searchInvoicesByNumber(ctx, number)
    }
    return listInvoices(ctx)
  }

  // ── /tasks ────────────────────────────────────────────────────────────────
  if (method === 'GET' && path === '/tasks') {
    return listTasks(ctx)
  }

  return null
}
