import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/db'
import { getSession, hashPassword, isAdmin } from '@/lib/auth'
import { z } from 'zod'

const updateUserSchema = z.object({
  email: z.string().email().optional(),
  name: z.string().min(1).max(100).optional(),
  password: z.string().min(6).optional(),
  role: z.enum(['SERVER_ADMIN', 'TENANT_ADMIN', 'OPERATOR', 'VIEWER']).optional(),
  emailVerified: z.boolean().optional(),
  isActive: z.boolean().optional(),
})

export async function PATCH(
  req: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const session = await getSession()
    if (!session || !isAdmin(session.role)) {
      return NextResponse.json({ error: 'Nicht autorisiert' }, { status: 403 })
    }

    // TENANT_ADMIN: can only edit users in their own tenant
    if (session.role !== 'SERVER_ADMIN') {
      const target = await (prisma as any).user.findUnique({
        where: { id: params.id },
        include: { memberships: true },
      })
      if (!target) return NextResponse.json({ error: 'Benutzer nicht gefunden' }, { status: 404 })
      const inSameTenant = target.memberships?.some((m: any) => m.tenantId === session.tenantId)
      if (!inSameTenant) return NextResponse.json({ error: 'Keine Berechtigung' }, { status: 403 })
    }

    const body = await req.json()
    const data = updateUserSchema.parse(body)

    // TENANT_ADMIN cannot promote to SERVER_ADMIN
    if (data.role === 'SERVER_ADMIN' && session.role !== 'SERVER_ADMIN') {
      return NextResponse.json({ error: 'Keine Berechtigung' }, { status: 403 })
    }

    const updateData: any = {}
    if (data.email) updateData.email = data.email
    if (data.name) updateData.name = data.name
    if (data.role) updateData.role = data.role
    if (data.password) updateData.password = await hashPassword(data.password)
    if (data.emailVerified !== undefined) updateData.emailVerified = data.emailVerified
    if (data.isActive !== undefined) {
      // Niemand darf sich selbst sperren
      if (data.isActive === false && session.id === params.id) {
        return NextResponse.json({ error: 'Eigenen Account kann man nicht sperren' }, { status: 400 })
      }
      updateData.isActive = data.isActive
    }

    const user = await (prisma as any).user.update({
      where: { id: params.id },
      data: updateData,
      select: {
        id: true,
        email: true,
        name: true,
        role: true,
        emailVerified: true,
        isActive: true,
        lastLoginAt: true,
        createdAt: true,
        updatedAt: true,
      },
    })

    return NextResponse.json({ user })
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json({ error: 'Ungültige Daten' }, { status: 400 })
    }
    console.error('Error updating user:', error)
    return NextResponse.json({ error: 'Interner Fehler' }, { status: 500 })
  }
}

export async function DELETE(
  req: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const session = await getSession()
    if (!session || !isAdmin(session.role)) {
      return NextResponse.json({ error: 'Nicht autorisiert' }, { status: 403 })
    }

    const target = await (prisma as any).user.findUnique({
      where: { id: params.id },
      include: { memberships: true },
    })
    if (!target) {
      return NextResponse.json({ error: 'Benutzer nicht gefunden' }, { status: 404 })
    }

    // TENANT_ADMIN: can only delete users in their own tenant
    if (session.role !== 'SERVER_ADMIN') {
      const inSameTenant = target.memberships?.some((m: any) => m.tenantId === session.tenantId)
      if (!inSameTenant) return NextResponse.json({ error: 'Keine Berechtigung' }, { status: 403 })
    }

    // Prevent deleting yourself
    if (session.id === params.id) {
      return NextResponse.json({ error: 'Eigenen Account kann nicht gelöscht werden' }, { status: 400 })
    }

    // Reassign projects to tenant admin before deleting
    for (const membership of (target.memberships || [])) {
      // Find a TENANT_ADMIN in the same tenant (not the user being deleted)
      const adminMembership = await (prisma as any).tenantMembership.findFirst({
        where: {
          tenantId: membership.tenantId,
          userId: { not: params.id },
          role: 'TENANT_ADMIN',
        },
      })
      const newOwnerId = adminMembership?.userId || session.id
      // Reassign all projects owned by this user in this tenant
      await (prisma as any).project.updateMany({
        where: { ownerId: params.id, tenantId: membership.tenantId },
        data: { ownerId: newOwnerId },
      })
    }
    // Also reassign any projects without a tenant
    await (prisma as any).project.updateMany({
      where: { ownerId: params.id },
      data: { ownerId: session.id },
    })

    await (prisma as any).user.delete({ where: { id: params.id } })
    return NextResponse.json({ success: true })
  } catch (error: any) {
    console.error('Error deleting user:', error)
    const msg = error?.code === 'P2003'
      ? 'Benutzer kann nicht gelöscht werden — es gibt noch abhängige Daten.'
      : 'Interner Fehler beim Löschen des Benutzers'
    return NextResponse.json({ error: msg }, { status: 500 })
  }
}
