/**
 * Admin impersonation — POST /api/admin/tenants/:slug/impersonate
 *
 * Mints a short-lived impersonation JWT (15 min) for the given tenant.
 * Requires admin session + admin.tenants:write permission.
 * Emits admin.impersonation_started to writeAdminAuditLog.
 *
 * The JWT is returned as { token } — the admin UI redirects the browser to
 * https://app.zync.is/impersonate?token=<token> which exchanges it for a
 * zync_session cookie.
 */
import { Hono } from 'hono'
import type { AppEnv } from '../../types'
import { adminAuthMiddleware } from '../../middleware/admin-auth'
import { requireAdminSession } from '../../middleware/guards'
import { requireAdminPermission } from '@zync/auth'
import { signImpersonationToken } from '@zync/auth'
import { createDb, getTenantDetailAdmin, writeAdminAuditLog } from '@zync/db/queries'
import type { AdminSessionPayload } from '@zync/types'

export const adminImpersonateRoute = new Hono<AppEnv>()

adminImpersonateRoute.use('*', adminAuthMiddleware)
adminImpersonateRoute.use('*', requireAdminSession())
adminImpersonateRoute.use('*', requireAdminPermission('admin.tenants:write'))

// POST /api/admin/tenants/:slug/impersonate
adminImpersonateRoute.post('/:slug/impersonate', async (c) => {
  const adminSession = c.get('session') as AdminSessionPayload
  const { slug } = c.req.param()

  const db = createDb(c.env)
  const tenant = await getTenantDetailAdmin(db, slug)
  if (!tenant) {
    return c.json({ error: 'Tenant not found' }, 404)
  }

  // Spec: reject frozen tenants — status is always 'active' for v1 but guard anyway
  if (tenant.status === 'frozen' || tenant.status === 'suspended') {
    return c.json({ error: 'Cannot impersonate a frozen or suspended tenant' }, 422)
  }

  const token = await signImpersonationToken(
    {
      sub: `admin:${adminSession.sub}`,
      tenant_id: tenant.id,
      tenant_slug: tenant.slug,
      impersonated_as: 'owner',
      type: 'impersonation',
    },
    c.env.IMPERSONATION_SECRET,
  )

  // Audit: admin-plane impersonation started
  await writeAdminAuditLog(db, {
    tenantId: tenant.id,
    actorId: adminSession.sub,
    entityType: 'tenant',
    entityId: tenant.id,
    action: 'admin.impersonation_started',
    changes: { tenant_slug: [null, tenant.slug] },
    ip: c.req.header('cf-connecting-ip') ?? c.req.header('x-forwarded-for') ?? null,
  })

  return c.json({ token })
})
