/**
 * GET /api/catalog/:token/public — public catalog proxy endpoint.
 * wave-11 leaf-C (public-catalog-page).
 *
 * No auth. Rate-limited by RATE_LIMITER_CATALOG (30 req/min per IP+token).
 * Resolves catalog_shares + catalog_templates by public_token.
 * Emits one catalog_view Analytics Engine event per successful load.
 * Sets Cache-Control: no-store so the view event fires each load.
 */
import { Hono } from 'hono'
import type { Context } from 'hono'
import { createDb, getCatalogShareByToken, getWhiteLabelConfig, getTenantById, getLeadForm } from '@zync/db/queries'
import type { AppEnv } from '../types'
import { TenantTier, type CatalogPublicResponse, type TenantId } from '@zync/types'

// ── Helpers ───────────────────────────────────────────────────────────────────

async function getTenantBranding(
  db: ReturnType<typeof createDb>,
  tenantId: string,
  tenantName: string,
  tenantTier: TenantTier,
): Promise<CatalogPublicResponse['tenantBranding']> {
  // getWhiteLabelConfig returns the white_label_configs row (may be null)
  const wl = await getWhiteLabelConfig(db, tenantId)
  return {
    tenantId,
    tenantTier,
    logoR2Key: wl?.logoUrl ?? null,
    primaryColor: wl?.primaryColor ?? null,
    tenantName,
    customDomain: wl?.customDomain ?? null,
  }
}

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

export const catalogPublicRoute = new Hono<AppEnv>()

function getTokenOrResponse(c: Context<AppEnv>) {
  const token = c.req.param('token')
  if (!token) {
    return { response: c.json({ error: 'catalog_not_found' }, 404) }
  }
  return { token }
}

async function handleCatalogPublicRequest(c: Context<AppEnv>) {
  const tokenResult = getTokenOrResponse(c)
  if ('response' in tokenResult) {
    return tokenResult.response
  }
  const { token } = tokenResult
  const ip = c.req.header('CF-Connecting-IP') ?? c.req.header('x-forwarded-for') ?? 'unknown'

  // Rate limit: 30 req/min per token:ip
  const { success } = await (async () => { try { const _r = await c.env.RATE_LIMITER_CATALOG?.limit({ key: `${token}:${ip}` }); return _r ?? { success: true }; } catch { return { success: true }; } })()
  if (!success) {
    return c.json({ error: 'rate_limited' }, 429)
  }

  const db = createDb(c.env)
  const data = await getCatalogShareByToken(db, token)

  if (!data) {
    return c.json({ error: 'catalog_not_found' }, 404)
  }

  // Load tenant name for branding
  const tenant = await getTenantById(db, data.tenantId as unknown as TenantId)
  const tenantName = tenant?.name ?? 'Unknown'
  const tenantTier = (tenant?.tier ?? TenantTier.BUSINESS) as TenantTier

  const shareSettings = (data.settings as { lead_form_id?: string | null }) ?? {}
  const leadFormId = shareSettings.lead_form_id

  // Fetch lead form config if share has one (parallel with branding)
  const [branding, leadFormRow] = await Promise.all([
    getTenantBranding(db, data.tenantId, tenantName, tenantTier),
    leadFormId ? getLeadForm(db, data.tenantId, leadFormId) : Promise.resolve(null),
  ])

  // Emit catalog_view Analytics Engine event (exactly once per successful load)
  c.env.ANALYTICS_ENGINE.writeDataPoint({
    blobs: [
      data.tenantId,
      data.shareId,
      data.utmSource ?? '',
      data.utmMedium ?? '',
      data.utmCampaign ?? '',
    ],
    indexes: [data.tenantId],
  })

  const response: CatalogPublicResponse = {
    template: {
      content: data.content as CatalogPublicResponse['template']['content'],
    },
    share: {
      id: data.shareId,
      settings: shareSettings,
      utmParams: {
        utmSource: data.utmSource,
        utmMedium: data.utmMedium,
        utmCampaign: data.utmCampaign,
      },
    },
    tenantBranding: branding,
    leadForm: leadFormRow?.isActive
      ? { slug: leadFormRow.slug, fields: leadFormRow.fields }
      : null,
  }

  c.header('Cache-Control', 'no-store')
  c.header('Content-Type', 'application/json')
  return c.json(response, 200)
}

catalogPublicRoute.get('/:token/public', handleCatalogPublicRequest)
catalogPublicRoute.get('/:token', handleCatalogPublicRequest)
