/**
 * Two-factor auth write helpers — auth-2fa.
 *
 * All tenant-scoped mutations run inside db.transaction with an audit_log row.
 */
import { eq } from 'drizzle-orm'
import type { TenantId, UserId } from '@zync/types'
import type { Db } from '../client'
import { users, tenants } from '../schema'
import { auditLog } from './_audit-forward'

/**
 * Enable 2FA for a user: set two_factor_enabled=true, phone hash, and suffix.
 * Audit-logged as a tenant-scoped event.
 */
export async function enable2FA(
  db: Db,
  args: {
    userId: UserId
    tenantId: TenantId
    phoneHash: string
    phoneSuffix: string
    actorIp?: string | null
    requestId?: string | null
  },
): Promise<void> {
  await db.transaction(async (tx) => {
    await tx
      .update(users)
      .set({
        twoFactorEnabled: true,
        twoFactorPhone: args.phoneHash,
        twoFactorPhoneSuffix: args.phoneSuffix,
      })
      .where(eq(users.id, args.userId))

    await tx.insert(auditLog).values({
      tenantId: args.tenantId,
      actorId: args.userId,
      actorType: 'user',
      entityType: 'two_factor',
      entityId: args.userId,
      action: 'two_factor.enabled',
      ip: args.actorIp ?? null,
      requestId: args.requestId ?? null,
    })
  })
}

/**
 * Disable 2FA for a user: clear two_factor_enabled, phone hash, and suffix.
 * Audit-logged.
 */
export async function disable2FA(
  db: Db,
  args: {
    userId: UserId
    tenantId: TenantId
    actorIp?: string | null
    requestId?: string | null
  },
): Promise<void> {
  await db.transaction(async (tx) => {
    await tx
      .update(users)
      .set({
        twoFactorEnabled: false,
        twoFactorPhone: null,
        twoFactorPhoneSuffix: null,
      })
      .where(eq(users.id, args.userId))

    await tx.insert(auditLog).values({
      tenantId: args.tenantId,
      actorId: args.userId,
      actorType: 'user',
      entityType: 'two_factor',
      entityId: args.userId,
      action: 'two_factor.disabled',
      ip: args.actorIp ?? null,
      requestId: args.requestId ?? null,
    })
  })
}

/**
 * Update tenant 2FA enforcement settings.
 * Audit-logged as a settings change.
 */
export async function updateTenant2FASettings(
  db: Db,
  args: {
    tenantId: TenantId
    enforce2fa?: boolean
    disable2faRememberDevice?: boolean
    actorId: UserId
    actorIp?: string | null
    requestId?: string | null
  },
): Promise<void> {
  await db.transaction(async (tx) => {
    const update: Record<string, boolean> = {}
    if (args.enforce2fa !== undefined) update['enforce2fa'] = args.enforce2fa
    if (args.disable2faRememberDevice !== undefined)
      update['disable2faRememberDevice'] = args.disable2faRememberDevice

    if (Object.keys(update).length > 0) {
      await tx
        .update(tenants)
        .set(update)
        .where(eq(tenants.id, args.tenantId))
    }

    await tx.insert(auditLog).values({
      tenantId: args.tenantId,
      actorId: args.actorId,
      actorType: 'user',
      entityType: 'tenant',
      entityId: args.tenantId,
      action: 'tenant.2fa_settings.updated',
      changes: {
        ...(args.enforce2fa !== undefined
          ? { enforce_2fa: [null, args.enforce2fa] as [unknown, unknown] }
          : {}),
        ...(args.disable2faRememberDevice !== undefined
          ? { disable_2fa_remember_device: [null, args.disable2faRememberDevice] as [unknown, unknown] }
          : {}),
      },
      ip: args.actorIp ?? null,
      requestId: args.requestId ?? null,
    })
  })
}
