import { NextRequest, NextResponse } from 'next/server';
import { auth, clerkClient } from '@clerk/nextjs/server';
import { connectDB } from '@/lib/mongodb';
import User from '@/models/User';
import { Types } from 'mongoose';

export async function PUT(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    await connectDB();

    const { userId } = await auth();
    if (!userId) {
      return NextResponse.json(
        { error: 'Authentication required', code: 'UNAUTHORIZED' },
        { status: 401 }
      );
    }

    const requestingUser = await User.findOne({ clerkId: userId }).lean();

    if (!requestingUser) {
      return NextResponse.json(
        { error: 'User not found', code: 'USER_NOT_FOUND' },
        { status: 404 }
      );
    }

    if (requestingUser.role !== 'admin' && requestingUser.role !== 'super_admin') {
      return NextResponse.json(
        { error: 'Admin access required', code: 'FORBIDDEN' },
        { status: 403 }
      );
    }

    const { id } = await params;

    if (!Types.ObjectId.isValid(id)) {
      return NextResponse.json(
        { error: 'Valid ID is required', code: 'INVALID_ID' },
        { status: 400 }
      );
    }

    const targetUser = await User.findById(id);

    if (!targetUser) {
      return NextResponse.json(
        { error: 'User not found', code: 'USER_NOT_FOUND' },
        { status: 404 }
      );
    }

    // Protection Logic: Admin cannot modify Admin or Super Admin
    if ((targetUser.role === 'admin' || targetUser.role === 'super_admin') && requestingUser.role !== 'super_admin') {
      return NextResponse.json(
        { error: 'You do not have permission to modify this user.', code: 'FORBIDDEN_SUPER_ADMIN_ONLY' },
        { status: 403 }
      );
    }

    const body = await request.json();
    const { name, email, phone, role } = body;

    if (role && role !== 'user' && role !== 'admin' && role !== 'staff' && role !== 'super_admin') {
      return NextResponse.json(
        { error: 'Role must be either "user", "staff", "admin" or "super_admin"', code: 'INVALID_ROLE' },
        { status: 400 }
      );
    }

    // Prevent Admin from assigning Super Admin role
    if (role === 'super_admin' && requestingUser.role !== 'super_admin') {
      return NextResponse.json(
        { error: 'Only Super Admin can assign the Super Admin role.', code: 'FORBIDDEN_SUPER_ADMIN_REQUIRED' },
        { status: 403 }
      );
    }

    if (email) {
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      if (!emailRegex.test(email)) {
        return NextResponse.json(
          { error: 'Invalid email format', code: 'INVALID_EMAIL' },
          { status: 400 }
        );
      }
    }

    const updateData: any = {
      updatedAt: new Date(),
    };

    if (name !== undefined) {
      updateData.name = name.trim();
    }
    if (email !== undefined) {
      updateData.email = email.trim().toLowerCase();
    }
    if (phone !== undefined) {
      updateData.phone = phone.trim();
    }
    if (role !== undefined) {
      updateData.role = role;
    }

    // Update Clerk Metadata if role is changed
    if (role) {
      try {
        const client = await clerkClient();
        await client.users.updateUserMetadata(targetUser.clerkId, {
          publicMetadata: {
            role: role,
          },
        });
      } catch (clerkError) {
        console.error('Failed to update Clerk metadata:', clerkError);
        // We continue to update DB, but log the error
      }
    }

    const updatedUser = await User.findByIdAndUpdate(id, updateData, { new: true }).lean();

    return NextResponse.json(updatedUser, { status: 200 });
  } catch (error: any) {
    console.error('PUT error:', error);
    return NextResponse.json(
      { error: 'Internal server error: ' + error.message },
      { status: 500 }
    );
  }
}

export async function DELETE(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    await connectDB();

    const { userId } = await auth();
    if (!userId) {
      return NextResponse.json(
        { error: 'Authentication required', code: 'UNAUTHORIZED' },
        { status: 401 }
      );
    }

    const requestingUser = await User.findOne({ clerkId: userId }).lean();

    if (!requestingUser) {
      return NextResponse.json(
        { error: 'User not found', code: 'USER_NOT_FOUND' },
        { status: 404 }
      );
    }

    if (requestingUser.role !== 'admin' && requestingUser.role !== 'super_admin') {
      return NextResponse.json(
        { error: 'Admin access required', code: 'FORBIDDEN' },
        { status: 403 }
      );
    }

    const { id } = await params;

    if (!Types.ObjectId.isValid(id)) {
      return NextResponse.json(
        { error: 'Valid ID is required', code: 'INVALID_ID' },
        { status: 400 }
      );
    }

    const targetUser = await User.findById(id);

    if (!targetUser) {
      return NextResponse.json(
        { error: 'User not found', code: 'USER_NOT_FOUND' },
        { status: 404 }
      );
    }

    // Protection Logic: Admin cannot delete Admin or Super Admin
    if ((targetUser.role === 'admin' || targetUser.role === 'super_admin') && requestingUser.role !== 'super_admin') {
      return NextResponse.json(
        { error: 'You do not have permission to delete this user.', code: 'FORBIDDEN_SUPER_ADMIN_ONLY' },
        { status: 403 }
      );
    }

    if (targetUser.clerkId === userId) {
      return NextResponse.json(
        { error: 'Cannot delete your own account', code: 'CANNOT_DELETE_SELF' },
        { status: 400 }
      );
    }

    // Delete from Clerk first
    try {
      const client = await clerkClient();
      await client.users.deleteUser(targetUser.clerkId);
    } catch (clerkError) {
      console.error('Failed to delete user from Clerk:', clerkError);
      // We continue to delete from DB to keep local consistency, 
      // but ideally this should be atomic or have better error handling.
      // For now, logging detailed error is sufficient.
    }

    const deletedUser = await User.findByIdAndDelete(id).lean();

    return NextResponse.json(
      {
        message: 'User deleted successfully',
        user: deletedUser,
      },
      { status: 200 }
    );
  } catch (error: any) {
    console.error('DELETE error:', error);
    return NextResponse.json(
      { error: 'Internal server error: ' + error.message },
      { status: 500 }
    );
  }
}