<?php

namespace App\Console\Commands;

use App\Models\Department;
use App\Models\User;
use Illuminate\Console\Command;

class AssignDepartmentToUsers extends Command
{
    protected $signature = 'users:assign-department
                            {--user= : ID, email ou matricule de l\'utilisateur}
                            {--department= : ID du département}
                            {--list : Afficher les utilisateurs et leurs départements}
                            {--role= : Filtrer par rôle (ex: Responsable du département)}';

    protected $description = 'Associer les départements aux utilisateurs';

    public function handle(): int
    {
        if ($this->option('list')) {
            return $this->listUsers();
        }

        if ($this->option('user') && $this->option('department')) {
            return $this->assignFromOptions();
        }

        return $this->interactiveMode();
    }

    protected function listUsers(): int
    {
        $query = User::with('department')->orderBy('full_name');

        if ($role = $this->option('role')) {
            try {
                $query->role($role);
            } catch (\Spatie\Permission\Exceptions\RoleDoesNotExist $e) {
                $this->warn("Rôle non trouvé : {$role}. Affichage de tous les utilisateurs.");
            }
        }

        $users = $query->get();

        if ($users->isEmpty()) {
            $this->warn('Aucun utilisateur trouvé.');
            return self::FAILURE;
        }

        $rows = $users->map(fn ($u) => [
            $u->id,
            $u->matricule,
            $u->full_name,
            $u->email,
            $u->roles->pluck('name')->join(', ') ?: '-',
            $u->department?->name ?? '<non assigné>',
            $u->department_id ?? '-',
        ])->toArray();

        $this->table(
            ['ID', 'Matricule', 'Nom', 'Email', 'Rôle(s)', 'Département', 'department_id'],
            $rows
        );

        $this->newLine();
        $this->info('Pour assigner un département :');
        $this->line('  php artisan users:assign-department --user=<id|email|matricule> --department=<id>');
        $this->line('  php artisan users:assign-department  (mode interactif)');

        return self::SUCCESS;
    }

    protected function assignFromOptions(): int
    {
        $userInput = $this->option('user');
        $departmentId = (int) $this->option('department');

        $user = $this->findUser($userInput);
        if (!$user) {
            $this->error("Utilisateur non trouvé : {$userInput}");
            return self::FAILURE;
        }

        $department = Department::whereDeletedAt(null)->find($departmentId);
        if (!$department) {
            $this->error("Département non trouvé : {$departmentId}");
            return self::FAILURE;
        }

        $user->department_id = $department->id;
        $user->save();

        $this->info("✓ {$user->full_name} a été associé au département : {$department->name}");

        return self::SUCCESS;
    }

    protected function interactiveMode(): int
    {
        $query = User::with(['department', 'roles'])->orderBy('full_name');

        if ($role = $this->option('role')) {
            try {
                $query->role($role);
            } catch (\Spatie\Permission\Exceptions\RoleDoesNotExist $e) {
                $this->warn("Rôle non trouvé : {$role}. Affichage de tous les utilisateurs.");
            }
        }

        $users = $query->get();

        if ($users->isEmpty()) {
            $this->warn('Aucun utilisateur trouvé.');
            return self::FAILURE;
        }

        $departments = Department::whereDeletedAt(null)->orderBy('name')->get();
        if ($departments->isEmpty()) {
            $this->warn('Aucun département trouvé.');
            return self::FAILURE;
        }

        $userChoices = $users->mapWithKeys(fn ($u) => [
            $u->id => "{$u->full_name} ({$u->email}) - " . ($u->department?->name ?? 'non assigné'),
        ])->all();

        $userId = (int) $this->choice('Sélectionner un utilisateur', $userChoices);
        $user = $users->first(fn ($u) => (int) $u->id === $userId);

        $departmentChoices = ['0' => 'Aucun département (retirer l\'association)'] + $departments->mapWithKeys(fn ($d) => [
            (string) $d->id => "{$d->name} ({$d->reference})",
        ])->all();

        $selected = $this->choice('Sélectionner le département', $departmentChoices);
        $departmentId = (int) $selected;
        $department = $departmentId === 0 ? null : $departments->first(fn ($d) => (int) $d->id === $departmentId);

        $user->department_id = $department?->id;
        $user->save();

        if ($department) {
            $this->info("✓ {$user->full_name} a été associé au département : {$department->name}");
        } else {
            $this->info("✓ L'association au département a été retirée pour {$user->full_name}");
        }

        if ($this->confirm('Associer un autre utilisateur ?', false)) {
            return $this->interactiveMode();
        }

        return self::SUCCESS;
    }

    protected function findUser(string $input): ?User
    {
        return User::where('id', $input)
            ->orWhere('email', $input)
            ->orWhere('matricule', $input)
            ->first();
    }
}
