<?php

namespace App\Http\Livewire\Admin;

use App\Models\Departamento;
use App\Models\User;
use App\Support\ModuloPortal;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
use Livewire\Component;
use Livewire\WithFileUploads;
use Livewire\WithPagination;
use Spatie\Permission\Models\Role;

class Usuarios extends Component
{
    use WithFileUploads;
    use WithPagination;

    public string $busca = '';
    public bool $modalAberto = false;
    public ?int $usuarioEditandoId = null;
    public string $name = '';
    public string $email = '';
    public string $password = '';
    public ?int $departamento_id = null;
    public string $papel = 'Colaborador';
    public bool $ativo = true;
    public array $modulosSelecionados = ['wiki.visualizar'];
    public $fotoPerfil = null;

    protected $paginationTheme = 'tailwind';

    public function mount(): void
    {
        abort_unless(Auth::user()?->hasRole('Administrador Master'), 403);
    }

    public function updatedBusca(): void
    {
        $this->resetPage();
    }

    public function abrirCriacao(): void
    {
        $this->resetFormulario();
        $this->modalAberto = true;
    }

    public function editar(int $usuarioId): void
    {
        $usuario = User::with(['roles', 'permissions'])->findOrFail($usuarioId);

        $this->usuarioEditandoId = $usuario->id;
        $this->name = $usuario->name;
        $this->email = $usuario->email;
        $this->departamento_id = $usuario->departamento_id;
        $this->papel = $usuario->roles->first()?->name ?: 'Colaborador';
        $this->ativo = (bool) $usuario->ativo;
        $this->password = '';
        $this->modulosSelecionados = collect(ModuloPortal::permissoes())
            ->filter(fn (string $permissao) => $usuario->can($permissao))
            ->values()
            ->all();

        $this->modalAberto = true;
    }

    public function salvar(): void
    {
        $dados = $this->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'max:255', Rule::unique('users', 'email')->ignore($this->usuarioEditandoId)],
            'password' => [$this->usuarioEditandoId ? 'nullable' : 'required', 'string', 'min:8'],
            'departamento_id' => ['nullable', 'exists:departamentos,id'],
            'papel' => ['required', Rule::exists('roles', 'name')],
            'ativo' => ['boolean'],
            'fotoPerfil' => ['nullable', 'image', 'max:2048'],
            'modulosSelecionados' => ['array'],
            'modulosSelecionados.*' => [Rule::in(ModuloPortal::permissoes())],
        ]);

        if ($this->usuarioEditandoId === Auth::id() && (! $dados['ativo'] || $dados['papel'] !== 'Administrador Master')) {
            $this->addError('papel', 'Voce nao pode remover seu proprio acesso de Administrador Master.');
            return;
        }

        $payload = [
            'name' => $dados['name'],
            'email' => $dados['email'],
            'departamento_id' => $dados['departamento_id'],
            'ativo' => $dados['ativo'],
        ];

        if ($dados['password']) {
            $payload['password'] = Hash::make($dados['password']);
        }

        $usuario = User::updateOrCreate(['id' => $this->usuarioEditandoId], $payload);

        if ($this->fotoPerfil) {
            if ($usuario->foto_perfil) {
                Storage::disk('public')->delete($usuario->foto_perfil);
            }

            $usuario->forceFill([
                'foto_perfil' => $this->fotoPerfil->store('perfis', 'public'),
            ])->save();
        }

        $usuario->syncRoles([$dados['papel']]);
        $this->sincronizarPermissoesDeModulo($usuario, $dados['modulosSelecionados']);

        $this->modalAberto = false;
        $this->resetFormulario();
        $this->dispatchBrowserEvent('notify', ['message' => 'Usuario salvo com sucesso.']);
    }

    public function alternarAtivo(int $usuarioId): void
    {
        abort_if($usuarioId === Auth::id(), 403);

        $usuario = User::findOrFail($usuarioId);
        $usuario->update(['ativo' => ! $usuario->ativo]);

        $this->dispatchBrowserEvent('notify', ['message' => 'Status do usuario atualizado.']);
    }

    public function excluir(int $usuarioId): void
    {
        abort_if($usuarioId === Auth::id(), 403);

        User::findOrFail($usuarioId)->delete();
        $this->dispatchBrowserEvent('notify', ['message' => 'Usuario excluido.']);
    }

    public function render()
    {
        $usuarios = User::query()
            ->with(['departamento', 'roles', 'permissions'])
            ->when($this->busca, function ($query) {
                $termo = '%' . $this->busca . '%';

                $query->where(function ($subQuery) use ($termo) {
                    $subQuery->where('name', 'like', $termo)
                        ->orWhere('email', 'like', $termo);
                });
            })
            ->orderBy('name')
            ->paginate(10);

        return view('livewire.admin.usuarios', [
            'usuarios' => $usuarios,
            'departamentos' => Departamento::orderBy('nome')->get(),
            'papeis' => Role::orderBy('name')->pluck('name')->all(),
            'modulos' => ModuloPortal::todos(),
        ])->layout('layouts.app');
    }

    private function resetFormulario(): void
    {
        $this->reset(['usuarioEditandoId', 'name', 'email', 'password', 'departamento_id', 'fotoPerfil']);
        $this->papel = 'Colaborador';
        $this->ativo = true;
        $this->modulosSelecionados = ['wiki.visualizar'];
        $this->resetValidation();
    }

    private function sincronizarPermissoesDeModulo(User $usuario, array $permissoesSelecionadas): void
    {
        $permissoesDeModulo = ModuloPortal::permissoes();
        $permissoesDiretasNaoModulo = $usuario->permissions
            ->pluck('name')
            ->reject(fn (string $permissao) => in_array($permissao, $permissoesDeModulo, true))
            ->values()
            ->all();

        $usuario->syncPermissions(array_values(array_unique(array_merge(
            $permissoesDiretasNaoModulo,
            $permissoesSelecionadas
        ))));
    }
}
