<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
use Inertia\Inertia;
use Inertia\Response;
use Spatie\Permission\Models\Role;

class UserController extends Controller
{
    /**
     * Display a listing of the users.
     */
    public function index(Request $request): Response
    {
        $search = $request->input('search');
        $roleFilter = $request->input('role');

        $users = User::with('roles')
            ->when($search, function ($query, $search) {
                $query->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                        ->orWhere('email', 'like', "%{$search}%");
                });
            })
            ->when($roleFilter, function ($query, $roleFilter) {
                $query->whereHas('roles', function ($q) use ($roleFilter) {
                    $q->where('name', $roleFilter);
                });
            })
            ->latest()
            ->paginate(10)
            ->withQueryString();

        // Transform the paginated results for Inertia
        $users->getCollection()->transform(function ($user) {
            return [
                'id' => $user->id,
                'name' => $user->name,
                'email' => $user->email,
                'roles' => $user->roles->map(fn($role) => [
                    'id' => $role->id,
                    'name' => $role->name,
                ]),
                'created_at' => $user->created_at->format('Y-m-d H:i:s'),
            ];
        });

        $roles = Role::select('id', 'name')->get();

        return Inertia::render('Users/Index', [
            'users' => $users,
            'roles' => $roles,
            'filters' => [
                'search' => $search,
                'role' => $roleFilter,
            ],
        ]);
    }

    /**
     * Store a newly created user in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', Password::defaults()],
            'roles' => ['nullable', 'array'],
            'roles.*' => ['string', 'exists:roles,name'],
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        if ($request->has('roles')) {
            $user->syncRoles($request->roles);
        }

        // Audit Logging
        activity()
            ->performedOn($user)
            ->causedBy($request->user())
            ->withProperties(['roles' => $request->roles])
            ->log("Created user: {$user->name} ({$user->email})");

        return redirect()->back()->with('success', 'User created successfully.');
    }

    /**
     * Update the specified user in storage.
     */
    public function update(Request $request, User $user): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users,email,' . $user->id],
            'password' => ['nullable', Password::defaults()],
            'roles' => ['nullable', 'array'],
            'roles.*' => ['string', 'exists:roles,name'],
        ]);

        $oldRoles = $user->getRoleNames()->toArray();

        $user->update([
            'name' => $request->name,
            'email' => $request->email,
        ]);

        if ($request->filled('password')) {
            $user->update([
                'password' => Hash::make($request->password),
            ]);
        }

        if ($request->has('roles')) {
            $user->syncRoles($request->roles);
        }

        // Audit Logging
        activity()
            ->performedOn($user)
            ->causedBy($request->user())
            ->withProperties([
                'old_roles' => $oldRoles,
                'new_roles' => $request->roles,
            ])
            ->log("Updated user: {$user->name} ({$user->email})");

        return redirect()->back()->with('success', 'User updated successfully.');
    }

    /**
     * Remove the specified user from storage.
     */
    public function destroy(Request $request, User $user): RedirectResponse
    {
        if ($user->id === $request->user()->id) {
            return redirect()->back()->with('error', 'You cannot delete your own account.');
        }

        // Prevent deleting Super Admin users unless you are a Super Admin or restrict it
        // Since we want to be safe, let's prevent deleting the seed Super Admin user (id 1) or anyone with Super Admin role if we want, or just log it.
        if ($user->hasRole('Super Admin') && !$request->user()->hasRole('Super Admin')) {
            return redirect()->back()->with('error', 'Only Super Admins can delete other Super Admins.');
        }

        $userName = $user->name;
        $userEmail = $user->email;

        // Perform audit log BEFORE deleting so relation works
        activity()
            ->performedOn($user)
            ->causedBy($request->user())
            ->log("Deleted user: {$userName} ({$userEmail})");

        $user->delete();

        return redirect()->back()->with('success', 'User deleted successfully.');
    }
}
