/**
 * Portal profile routes — tenant-portals (wave 9d, Task 9).
 *
 * PATCH /api/portal/profile
 * PATCH /api/portal/profile/password
 */
import { Hono } from 'hono'
import { hashPassword, revokeOtherPortalSessions, verifyPassword } from '@zync/auth'
import {
  getPortalProfile,
  updatePortalProfile,
  updatePortalUserPassword,
} from '@zync/db/queries'
import type { AppEnv } from '../../types'
import { portalAuthMiddleware, type PortalAuthVariables } from '../../middleware/portalAuth'
import { portalPasswordChangeSchema, portalProfileSchema } from '../../schemas/portalAuth'
import { withDoHash } from '../../lib/password-hash-do'

type PortalDataEnv = {
  Bindings: AppEnv['Bindings']
  Variables: PortalAuthVariables
}

export const portalProfileRoutes = new Hono<PortalDataEnv>()

portalProfileRoutes.use('*', portalAuthMiddleware)

portalProfileRoutes.get('/', async (c) => {
  const portal = c.get('portal')
  const db = c.get('db')

  const profile = await getPortalProfile(db, portal.tenantId, portal.customerId, portal.userId)
  if (!profile) return c.json({ error: 'Not found' }, 404)

  return c.json({
    name: profile.name,
    email: profile.email,
    locale: profile.locale,
  })
})

portalProfileRoutes.patch('/', async (c) => {
  const portal = c.get('portal')
  const db = c.get('db')

  const parsed = portalProfileSchema.safeParse(await c.req.json().catch(() => null))
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.issues }, 400)
  }

  if (parsed.data.name === undefined && parsed.data.locale === undefined) {
    return c.json({ error: 'No fields to update' }, 400)
  }

  const updated = await updatePortalProfile(db, portal.tenantId, portal.customerId, portal.userId, {
    name: parsed.data.name,
    locale: parsed.data.locale,
  })

  if (!updated) return c.json({ error: 'Not found' }, 404)

  return c.json({
    name: updated.name,
    email: updated.email,
    locale: updated.locale,
  })
})

portalProfileRoutes.patch('/password', async (c) => {
  const portal = c.get('portal')
  const db = c.get('db')

  const parsed = portalPasswordChangeSchema.safeParse(await c.req.json().catch(() => null))
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.issues }, 400)
  }

  const profile = await getPortalProfile(db, portal.tenantId, portal.customerId, portal.userId)
  if (!profile) return c.json({ error: 'Unauthorized' }, 401)

  const currentOk = await verifyPassword(
    parsed.data.currentPassword,
    profile.passwordHash,
    withDoHash(c.env),
  )
  if (!currentOk) {
    return c.json({ error: 'Incorrect password' }, 401)
  }

  const newHash = await hashPassword(parsed.data.newPassword, withDoHash(c.env))
  await updatePortalUserPassword(db, portal.userId, newHash)
  await revokeOtherPortalSessions(
    db,
    portal.tenantId,
    portal.customerId,
    portal.portalSessionId,
  )

  return c.body(null, 204)
})
