/**
 * POST /api/auth/signup — foundation-auth-rbac (Task 12).
 *
 * Creates a PENDING_EMAIL user (email_verified_at NULL), emails a signed
 * verification link, responds {userId}. No tenant exists yet, so this is a
 * single (non-audited) write — the tenant + OWNER membership are created at
 * verify-email time. Public route (no authMiddleware).
 */
import { Hono } from 'hono'
import type { ContentfulStatusCode } from 'hono/utils/http-status'
import { createDb } from '@zync/db/queries'
import type { TenantId, UserId } from '@zync/types'
import type { AppEnv } from '../../types'
import { signupSchema } from '../../schemas/auth'
import { dispatchSignup } from '../../lib/auth-write-do'
import { issueSessionForTenant } from '../../lib/issue-session'
import { appOriginForRequest } from '../../lib/origins'

export const signupRoute = new Hono<AppEnv>()

signupRoute.post('/signup', async (c) => {
  const ip = c.req.header('CF-Connecting-IP') ?? 'unknown'
  const rl = await (async () => { try { const _r = await c.env.RATE_LIMITER_AUTH?.limit({ key: `signup:${ip}` }); return _r ?? { success: true }; } catch { return { success: true }; } })()
  if (!rl.success) {
    return c.json({ error: 'Too many requests' }, 429)
  }

  const parsed = signupSchema.safeParse(await c.req.json())
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.flatten() }, 400)
  }
  const { email, password, businessName } = parsed.data

  // Offload the hash + DB write + email awaits to AuthWriteDO (30s budget, sticky
  // isolate) to escape the stateless pool's `exceededResources` kills. Falls back
  // inline when the DO is unconfigured or fails (signup is idempotent).
  const result = await dispatchSignup(c.env, { email, password, name: businessName, appOrigin: appOriginForRequest(c.req.url) })
  if (result.status < 200 || result.status >= 300) {
    return c.json(result.body as Record<string, unknown>, result.status as ContentfulStatusCode)
  }

  const body = result.body as { tenantId?: string | null; userId?: string }
  if (!body.userId || !body.tenantId) {
    return c.json(result.body as Record<string, unknown>, result.status as ContentfulStatusCode)
  }

  const issued = await issueSessionForTenant(
    c,
    createDb(c.env),
    body.userId as UserId,
    body.tenantId as TenantId,
  )
  if (!issued) {
    return c.json({ error: 'Failed to issue session' }, 500)
  }

  return c.json({ ok: true }, 201)
})
