import { NextRequest, NextResponse } from "next/server";
import { db, AdminRole, AdminStatus } from "@/lib/admin/db";
import { requireMainAdmin, getClientMetadata } from "@/lib/admin/auth";
import { SUB_ADMIN_ROLES } from "@/lib/admin/permissions";

export const dynamic = "force-dynamic";

export async function PATCH(
  req: NextRequest,
  context: { params: Promise<{ id: string }> }
) {
  try {
    const { user: mainAdmin } = await requireMainAdmin(req);
    const { ip } = getClientMetadata(req);
    const { id } = await context.params;

    const target = await db.getUserById(id);
    if (!target) {
      return NextResponse.json({ error: "Administrator not found." }, { status: 404 });
    }

    const body = await req.json();
    const newRole = body.role as AdminRole | undefined;
    const newStatus = body.status as AdminStatus | undefined;

    // Safety: Cannot modify Main Admin level or status via this endpoint
    if (target.level === "MAIN_ADMIN") {
      if (newRole && newRole !== "MAIN_ADMIN") {
        return NextResponse.json(
          { error: "The Main Administrator account cannot be demoted." },
          { status: 400 }
        );
      }
      if (newStatus && newStatus !== "ACTIVE") {
        return NextResponse.json(
          { error: "The Main Administrator account cannot be suspended or deactivated." },
          { status: 400 }
        );
      }
    }

    const updates: { role?: AdminRole; status?: AdminStatus } = {};

    // Validate Role change
    if (newRole && newRole !== target.role) {
      if (target.level === "SUB_ADMIN") {
        const valid = SUB_ADMIN_ROLES.some((r) => r.id === newRole);
        if (!valid) {
          return NextResponse.json(
            { error: `Invalid role. Must be one of: ${SUB_ADMIN_ROLES.map((r) => r.id).join(", ")}` },
            { status: 400 }
          );
        }
      }
      updates.role = newRole;
    }

    // Validate Status change
    if (newStatus && newStatus !== target.status) {
      updates.status = newStatus;
    }

    if (Object.keys(updates).length === 0) {
      return NextResponse.json({ ok: true, user: target, message: "No changes detected." });
    }

    const updatedUser = await db.updateUser(target.id, updates);

    // If role changed or user suspended, immediately revoke active sessions
    if (updates.role || updates.status === "SUSPENDED" || updates.status === "DISABLED") {
      await db.revokeAllSessionsForUser(
        target.id,
        mainAdmin.email,
        updates.status === "SUSPENDED"
          ? "Account suspended by Main Admin"
          : "Role updated by Main Admin; re-authentication required"
      );
    }

    // Security Audit logging
    if (updates.role) {
      await db.logSecurityEvent({
        actorId: mainAdmin.id,
        actorName: mainAdmin.name,
        actorEmail: mainAdmin.email,
        actorLevel: mainAdmin.level,
        targetUserId: target.id,
        targetUserEmail: target.email,
        targetUserName: target.name,
        action: "ROLE_CHANGED",
        details: {
          previousRole: target.role,
          newRole: updates.role,
        },
        ipAddress: ip,
      });
    }

    if (updates.status) {
      await db.logSecurityEvent({
        actorId: mainAdmin.id,
        actorName: mainAdmin.name,
        actorEmail: mainAdmin.email,
        actorLevel: mainAdmin.level,
        targetUserId: target.id,
        targetUserEmail: target.email,
        targetUserName: target.name,
        action: updates.status === "ACTIVE" ? "ADMIN_REACTIVATED" : "ADMIN_SUSPENDED",
        details: {
          previousStatus: target.status,
          newStatus: updates.status,
        },
        ipAddress: ip,
      });
    }

    return NextResponse.json({
      ok: true,
      user: {
        id: updatedUser.id,
        email: updatedUser.email,
        name: updatedUser.name,
        level: updatedUser.level,
        role: updatedUser.role,
        status: updatedUser.status,
      },
      message: "Administrator updated successfully.",
    });
  } catch (error) {
    const status = (error as unknown as { status: number }).status || 500;
    return NextResponse.json(
      { error: (error as Error).message || "Failed to update administrator." },
      { status }
    );
  }
}
