import { NextRequest, NextResponse } from 'next/server'
import { getUserFromRequest, getAllUsers, createUser, updateUser, deleteUser, getUserById, requireRole } from '@/lib/auth'
import { logAuditEvent } from '@/lib/db'
import { validateBody, createUserSchema } from '@/lib/validation'
import { mutationLimiter } from '@/lib/rate-limit'
import { logger } from '@/lib/logger'

/**
 * GET /api/auth/users - List all users (admin only)
 */
export async function GET(request: NextRequest) {
  const auth = requireRole(request, 'viewer')
  if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status })

  const user = getUserFromRequest(request)
  if (!user || user.role !== 'admin') {
    return NextResponse.json({ error: 'Admin access required' }, { status: 403 })
  }

  const users = getAllUsers()
  const workspaceId = user.workspace_id ?? 1
  return NextResponse.json({ users: users.filter((u) => (u.workspace_id ?? 1) === workspaceId) })
}

/**
 * POST /api/auth/users - Create a new user (admin only)
 */
export async function POST(request: NextRequest) {
  const currentUser = getUserFromRequest(request)
  if (!currentUser || currentUser.role !== 'admin') {
    return NextResponse.json({ error: 'Admin access required' }, { status: 403 })
  }

  const rateCheck = mutationLimiter(request)
  if (rateCheck) return rateCheck

  try {
    const result = await validateBody(request, createUserSchema)
    if ('error' in result) return result.error
    const { username, password, display_name, role, provider, email } = result.data

    const workspaceId = currentUser.workspace_id ?? 1
    const newUser = createUser(username, password, display_name || username, role, {
      provider,
      email: email || null,
      workspace_id: workspaceId,
    })

    const ipAddress = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || 'unknown'
    logAuditEvent({
      action: 'user_create', actor: currentUser.username, actor_id: currentUser.id,
      target_type: 'user', target_id: newUser.id,
      detail: { username, role, provider, email }, ip_address: ipAddress,
    })

    return NextResponse.json({
      user: {
        id: newUser.id,
        username: newUser.username,
        display_name: newUser.display_name,
        role: newUser.role,
        provider: newUser.provider || 'local',
        email: newUser.email || null,
        avatar_url: newUser.avatar_url || null,
        is_approved: newUser.is_approved ?? 1,
        workspace_id: newUser.workspace_id ?? 1,
        tenant_id: newUser.tenant_id ?? 1,
      }
    }, { status: 201 })
  } catch (error: any) {
    if (error.message?.includes('UNIQUE constraint failed')) {
      return NextResponse.json({ error: 'Username already exists' }, { status: 409 })
    }
    logger.error({ err: error }, 'POST /api/auth/users error')
    return NextResponse.json({ error: 'Failed to create user' }, { status: 500 })
  }
}

/**
 * PUT /api/auth/users - Update a user (admin only)
 */
export async function PUT(request: NextRequest) {
  const currentUser = getUserFromRequest(request)
  if (!currentUser || currentUser.role !== 'admin') {
    return NextResponse.json({ error: 'Admin access required' }, { status: 403 })
  }

  try {
    const { id, display_name, role, password, is_approved, email, avatar_url } = await request.json()
    const userId = parseInt(String(id))

    if (!id || Number.isNaN(userId)) {
      return NextResponse.json({ error: 'User ID is required' }, { status: 400 })
    }

    if (role && !['admin', 'operator', 'viewer'].includes(role)) {
      return NextResponse.json({ error: 'Invalid role' }, { status: 400 })
    }

    // Prevent demoting yourself
    if (userId === currentUser.id && role && role !== currentUser.role) {
      return NextResponse.json({ error: 'Cannot change your own role' }, { status: 400 })
    }

    const workspaceId = currentUser.workspace_id ?? 1
    const existing = getUserById(userId)
    if (!existing || (existing.workspace_id ?? 1) !== workspaceId) {
      return NextResponse.json({ error: 'User not found' }, { status: 404 })
    }

    const updated = updateUser(userId, { display_name, role, password: password || undefined, is_approved, email, avatar_url })
    if (!updated) {
      return NextResponse.json({ error: 'User not found' }, { status: 404 })
    }

    const ipAddress = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || 'unknown'
    logAuditEvent({
      action: 'user_update', actor: currentUser.username, actor_id: currentUser.id,
      target_type: 'user', target_id: userId,
      detail: { display_name, role, password_changed: !!password, is_approved }, ip_address: ipAddress,
    })

    return NextResponse.json({
      user: {
        id: updated.id,
        username: updated.username,
        display_name: updated.display_name,
        role: updated.role,
        provider: updated.provider || 'local',
        email: updated.email || null,
        avatar_url: updated.avatar_url || null,
        is_approved: updated.is_approved ?? 1,
        workspace_id: updated.workspace_id ?? 1,
        tenant_id: updated.tenant_id ?? 1,
      }
    })
  } catch (error) {
    logger.error({ err: error }, 'PUT /api/auth/users error')
    return NextResponse.json({ error: 'Failed to update user' }, { status: 500 })
  }
}

/**
 * DELETE /api/auth/users - Delete a user (admin only)
 */
export async function DELETE(request: NextRequest) {
  const currentUser = getUserFromRequest(request)
  if (!currentUser || currentUser.role !== 'admin') {
    return NextResponse.json({ error: 'Admin access required' }, { status: 403 })
  }

  let body: any
  try { body = await request.json() } catch { return NextResponse.json({ error: 'Request body required' }, { status: 400 }) }
  const id = body.id

  if (!id) {
    return NextResponse.json({ error: 'User ID is required' }, { status: 400 })
  }

  const userId = parseInt(id)

  // Prevent deleting yourself
  if (userId === currentUser.id) {
    return NextResponse.json({ error: 'Cannot delete your own account' }, { status: 400 })
  }

  const workspaceId = currentUser.workspace_id ?? 1
  const existing = getUserById(userId)
  if (!existing || (existing.workspace_id ?? 1) !== workspaceId) {
    return NextResponse.json({ error: 'User not found' }, { status: 404 })
  }

  const deleted = deleteUser(userId)
  if (!deleted) {
    return NextResponse.json({ error: 'User not found' }, { status: 404 })
  }

  const ipAddress = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || 'unknown'
  logAuditEvent({
    action: 'user_delete', actor: currentUser.username, actor_id: currentUser.id,
    target_type: 'user', target_id: userId,
    ip_address: ipAddress,
  })

  return NextResponse.json({ success: true })
}
