<?php

namespace App\Livewire\Settings;

use App\Models\Assegnazione;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Livewire\Component;
use Spatie\Activitylog\Models\Activity;
use Spatie\Permission\Models\Role;

class UsersIndex extends Component
{
    public string $name = '';
    public string $email = '';
    public string $password = '';
    public string $password_confirmation = '';
    public string $selectedRole = '';
    public array $availableRoles = [];

    public ?int $editingUserId = null;
    public string $editName = '';
    public string $editEmail = '';
    public string $editPassword = '';
    public string $editPassword_confirmation = '';
    public string $editSelectedRole = '';

    public function mount(): void
    {
        $this->availableRoles = Role::query()
            ->orderBy('name')
            ->pluck('name')
            ->all();

        if (! empty($this->availableRoles)) {
            $this->selectedRole = $this->availableRoles[0];
        }
    }

    protected function rules(): array
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'max:255', Rule::unique('users', 'email')],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
            'selectedRole' => ['required', 'string', Rule::in($this->availableRoles)],
        ];
    }

    protected function editRules(): array
    {
        return [
            'editName' => ['required', 'string', 'max:255'],
            'editEmail' => [
                'required',
                'email',
                'max:255',
                Rule::unique('users', 'email')->ignore($this->editingUserId),
            ],
            'editPassword' => ['nullable', 'string', 'min:8', 'confirmed'],
            'editSelectedRole' => ['required', 'string', Rule::in($this->availableRoles)],
        ];
    }

    public function createUser(): void
    {
        $validated = $this->validate();

        $user = User::create([
            'name' => $validated['name'],
            'email' => $validated['email'],
            'password' => $validated['password'],
        ]);

        $user->syncRoles([$validated['selectedRole']]);

        $this->reset(['name', 'email', 'password', 'password_confirmation']);
        if (! empty($this->availableRoles)) {
            $this->selectedRole = $this->availableRoles[0];
        }
        session()->flash('success', 'Utente creato con successo.');
    }

    public function startEdit(int $userId): void
    {
        $user = User::query()->with('roles')->findOrFail($userId);

        $this->editingUserId = $user->id;
        $this->editName = $user->name;
        $this->editEmail = $user->email;
        $this->editPassword = '';
        $this->editPassword_confirmation = '';
        $this->editSelectedRole = $user->roles->first()?->name ?? ($this->availableRoles[0] ?? '');
    }

    public function cancelEdit(): void
    {
        $this->reset([
            'editingUserId',
            'editName',
            'editEmail',
            'editPassword',
            'editPassword_confirmation',
            'editSelectedRole',
        ]);
    }

    public function updateUser(): void
    {
        if (! $this->editingUserId) {
            return;
        }

        $validated = $this->validate($this->editRules());
        $user = User::query()->findOrFail($this->editingUserId);

        $user->name = $validated['editName'];
        $user->email = $validated['editEmail'];

        if (! empty($validated['editPassword'])) {
            $user->password = $validated['editPassword'];
        }

        $user->save();
        $user->syncRoles([$validated['editSelectedRole']]);

        $this->cancelEdit();
        session()->flash('success', 'Utente aggiornato con successo.');
    }

    public function deleteUser(int $userId): void
    {
        $currentUser = auth()->user();
        $user = User::query()->with('roles')->findOrFail($userId);

        if (! $currentUser || $currentUser->id === $user->id) {
            session()->flash('error', 'Non puoi cancellare il tuo utente.');
            return;
        }

        if ($user->hasRole('amministratore') && User::role('amministratore')->count() <= 1) {
            session()->flash('error', 'Non puoi cancellare l\'ultimo amministratore.');
            return;
        }

        DB::transaction(function () use ($user, $currentUser) {
            $causerName = $user->name;
            $causerEmail = $user->email;
            $deletedAt = now()->toDateTimeString();

            Activity::query()
                ->where('causer_type', User::class)
                ->where('causer_id', $user->id)
                ->chunkById(200, function ($activities) use ($causerName, $causerEmail, $deletedAt) {
                    foreach ($activities as $activity) {
                        $properties = $activity->properties?->toArray() ?? [];
                        $properties['causer_name'] = $causerName;
                        $properties['causer_email'] = $causerEmail;
                        $properties['causer_deleted_at'] = $deletedAt;

                        $activity->properties = $properties;
                        $activity->save();
                    }
                });

            Assegnazione::query()
                ->where('created_by', $user->id)
                ->update(['created_by' => $currentUser->id]);

            Assegnazione::query()
                ->where('returned_by', $user->id)
                ->update(['returned_by' => $currentUser->id]);

            $user->syncRoles([]);
            $user->delete();
        });

        if ($this->editingUserId === $userId) {
            $this->cancelEdit();
        }

        session()->flash('success', 'Utente cancellato. I log sono stati preservati.');
    }

    public function render()
    {
        return view('livewire.settings.users-index', [
            'users' => User::query()->with('roles')->orderBy('name')->get(),
        ]);
    }
}
