/**
 * AuthWriteDO — login / signup / verify-email WRITE offload (auth-write DO).
 *
 * SQLite-backed DO for the 30s CPU budget and a sticky isolate, so the
 * Hyperdrive + PasswordHashDO + email awaits run OFF the contended stateless
 * pool that was killing these requests with `exceededResources`. Secret-gated
 * via x-zync-authwrite + AUTHWRITE_DO_SECRET. Holds no state of its own; the
 * actual writes go to Postgres via createDb(env) inside the flow functions.
 */
import { DurableObject } from 'cloudflare:workers'
import { timingSafeEqual } from '@zync/auth'
import type { Env } from '@zync/types'
import { runSessionAuthentication } from '../lib/session-authentication'
import {
  runLogin,
  runSignup,
  runVerifyEmail,
  type LoginInput,
  type SignupInput,
  type VerifyEmailInput,
} from '../routes/auth/_auth-flows'

export class AuthWriteDO extends DurableObject<Env> {
  override async fetch(req: Request): Promise<Response> {
    const secret = this.env.AUTHWRITE_DO_SECRET
    const header = req.headers.get('x-zync-authwrite')
    if (!header || !secret || !timingSafeEqual(header, secret)) {
      return new Response(null, { status: 403 })
    }

    if (req.method !== 'POST') {
      return new Response(null, { status: 404 })
    }

    const url = new URL(req.url)
    try {
      if (url.pathname === '/authenticate') {
        const body = (await req.json()) as { token?: unknown }
        if (typeof body.token !== 'string' || !body.token) {
          return Response.json({ error: 'Invalid input' }, { status: 400 })
        }
        return Response.json(await runSessionAuthentication(this.env, body.token, this.ctx))
      }

      if (url.pathname === '/login') {
        const body = (await req.json()) as Partial<LoginInput>
        if (
          typeof body.email !== 'string' ||
          typeof body.password !== 'string' ||
          typeof body.reqUrl !== 'string' ||
          !body.headers ||
          typeof body.headers !== 'object'
        ) {
          return Response.json({ error: 'Invalid input' }, { status: 400 })
        }
        return await runLogin(this.env, {
          email: body.email,
          password: body.password,
          reqUrl: body.reqUrl,
          headers: Object.fromEntries(
            Object.entries(body.headers).filter(
              (entry): entry is [string, string] => typeof entry[1] === 'string',
            ),
          ),
        })
      }

      if (url.pathname === '/signup') {
        const body = (await req.json()) as Partial<SignupInput>
        if (
          typeof body.email !== 'string' ||
          typeof body.password !== 'string' ||
          typeof body.name !== 'string'
        ) {
          return Response.json({ error: 'Invalid input' }, { status: 400 })
        }
        const result = await runSignup(this.env, {
          email: body.email,
          password: body.password,
          name: body.name,
        })
        return Response.json({ status: result.status, body: result.body })
      }

      if (url.pathname === '/verify-email') {
        const body = (await req.json()) as Partial<VerifyEmailInput>
        if (typeof body.token !== 'string' || typeof body.reqUrl !== 'string') {
          return Response.json({ error: 'Invalid input' }, { status: 400 })
        }
        const input: VerifyEmailInput = {
          token: body.token,
          ip: typeof body.ip === 'string' ? body.ip : null,
          ray: typeof body.ray === 'string' ? body.ray : null,
          userAgent: typeof body.userAgent === 'string' ? body.userAgent : null,
          country: typeof body.country === 'string' ? body.country : null,
          reqUrl: body.reqUrl,
        }
        const result = await runVerifyEmail(this.env, input)
        return Response.json({
          status: result.status,
          redirect: result.redirect,
          setCookies: result.setCookies,
          body: result.body,
        })
      }

      return new Response(null, { status: 404 })
    } catch (err) {
      console.error('AuthWriteDO request failed', err instanceof Error ? err.name : typeof err)
      return Response.json({ error: 'Internal server error' }, { status: 500 })
    }
  }
}
