<?php

declare(strict_types=1);

require_once __DIR__ . '/../models/Usuario.php';
require_once __DIR__ . '/../models/Setor.php';

class UsuarioController extends Controller
{
    private array $perfis = ['ADMIN', 'TRIAGEM', 'SETOR', 'GESTOR'];

    public function index(): void
    {
        Auth::requireAdmin();

        $model = new Usuario();
        $usuarios = $model->todos();

        $this->view('usuarios/index', compact('usuarios'), 'admin');
    }

    public function create(): void
    {
        Auth::requireAdmin();

        $setores = (new Setor())->todos();
        $usuario = $this->defaultUser();
        $modo = 'create';
        $perfis = $this->perfis;

        $this->view('usuarios/form', compact('usuario', 'modo', 'setores', 'perfis'), 'admin');
    }

    public function store(): void
    {
        Auth::requireAdmin();

        $dados = $this->collectInput(true);
        $erros = $this->validate($dados, null, true);

        if (!empty($erros)) {
            Session::flash('erro', implode(' ', $erros));
            Session::set('usuario_form_data', $dados);
            $this->redirect('/admin/usuarios/create');
        }

        $dados['senha'] = password_hash((string) $dados['senha'], PASSWORD_DEFAULT);
        (new Usuario())->criar($dados);

        Session::flash('sucesso', 'Usuário administrativo cadastrado com sucesso.');
        $this->redirect('/admin/usuarios');
    }

    public function edit(): void
    {
        Auth::requireAdmin();

        $id = (int) ($_GET['id'] ?? 0);
        if ($id <= 0) {
            Session::flash('erro', 'Usuário não informado.');
            $this->redirect('/admin/usuarios');
        }

        $model = new Usuario();
        $usuario = $model->buscarPorId($id);
        if (!$usuario) {
            Session::flash('erro', 'Usuário não encontrado.');
            $this->redirect('/admin/usuarios');
        }

        $setores = (new Setor())->todos();
        $modo = 'edit';
        $perfis = $this->perfis;

        $this->view('usuarios/form', compact('usuario', 'modo', 'setores', 'perfis'), 'admin');
    }

    public function update(): void
    {
        Auth::requireAdmin();

        $id = (int) ($_POST['id'] ?? 0);
        if ($id <= 0) {
            Session::flash('erro', 'Usuário não informado.');
            $this->redirect('/admin/usuarios');
        }

        $dados = $this->collectInput(false);
        $erros = $this->validate($dados, $id, false);

        if (!empty($erros)) {
            Session::flash('erro', implode(' ', $erros));
            Session::set('usuario_form_data', array_merge($dados, ['id' => $id]));
            $this->redirect('/admin/usuarios/edit?id=' . $id);
        }

        if ($dados['senha'] !== '') {
            $dados['senha'] = password_hash((string) $dados['senha'], PASSWORD_DEFAULT);
        }

        $model = new Usuario();
        if (!$model->buscarPorId($id)) {
            Session::flash('erro', 'Usuário não encontrado.');
            $this->redirect('/admin/usuarios');
        }

        $model->atualizar($id, $dados);

        if ((int) (Auth::user()['id'] ?? 0) === $id) {
            $refresh = $model->buscarPorId($id);
            if ($refresh) {
                Auth::login($refresh);
            }
        }

        Session::flash('sucesso', 'Usuário atualizado com sucesso.');
        $this->redirect('/admin/usuarios');
    }

    private function defaultUser(): array
    {
        return [
            'id' => null,
            'nome' => '',
            'email' => '',
            'perfil' => 'TRIAGEM',
            'setor_id' => null,
            'ativo' => 1,
            'pode_visualizar_ocorrencias' => 1,
            'visualiza_todas_ocorrencias' => 1,
            'pode_editar_ocorrencias' => 1,
            'senha' => '',
        ];
    }

    private function collectInput(bool $create): array
    {
        $perfil = trim((string) ($_POST['perfil'] ?? 'TRIAGEM'));
        $setorId = isset($_POST['setor_id']) && $_POST['setor_id'] !== '' ? (int) $_POST['setor_id'] : null;
        $podeVisualizar = isset($_POST['pode_visualizar_ocorrencias']) ? 1 : 0;
        $visualizaTodas = isset($_POST['visualiza_todas_ocorrencias']) ? 1 : 0;
        $podeEditar = isset($_POST['pode_editar_ocorrencias']) ? 1 : 0;

        if ($perfil === 'ADMIN') {
            $setorId = null;
            $podeVisualizar = 1;
            $visualizaTodas = 1;
            $podeEditar = 1;
        }

        if ($podeVisualizar === 0) {
            $visualizaTodas = 0;
            $podeEditar = 0;
        }

        if ($visualizaTodas === 1) {
            $setorId = null;
        }

        return [
            'nome' => trim((string) ($_POST['nome'] ?? '')),
            'email' => mb_strtolower(trim((string) ($_POST['email'] ?? ''))),
            'perfil' => $perfil,
            'setor_id' => $setorId,
            'ativo' => isset($_POST['ativo']) ? 1 : 0,
            'pode_visualizar_ocorrencias' => $podeVisualizar,
            'visualiza_todas_ocorrencias' => $visualizaTodas,
            'pode_editar_ocorrencias' => $podeEditar,
            'senha' => (string) ($_POST['senha'] ?? ''),
        ];
    }

    private function validate(array $dados, ?int $id = null, bool $requirePassword = true): array
    {
        $erros = [];

        if ($dados['nome'] === '') {
            $erros[] = 'Informe o nome do usuário.';
        }

        if ($dados['email'] === '' || !filter_var($dados['email'], FILTER_VALIDATE_EMAIL)) {
            $erros[] = 'Informe um e-mail válido.';
        }

        if (!in_array($dados['perfil'], $this->perfis, true)) {
            $erros[] = 'Perfil inválido.';
        }

        if ($requirePassword && strlen($dados['senha']) < 6) {
            $erros[] = 'A senha deve ter pelo menos 6 caracteres.';
        }

        if (!$requirePassword && $dados['senha'] !== '' && strlen($dados['senha']) < 6) {
            $erros[] = 'A nova senha deve ter pelo menos 6 caracteres.';
        }

        if ((int) $dados['pode_visualizar_ocorrencias'] === 1 && (int) $dados['visualiza_todas_ocorrencias'] === 0 && empty($dados['setor_id'])) {
            $erros[] = 'Selecione um setor quando o usuário visualizar apenas ocorrências setoriais.';
        }

        $model = new Usuario();
        if ($dados['email'] !== '' && $model->emailEmUso($dados['email'], $id)) {
            $erros[] = 'Já existe outro usuário com este e-mail.';
        }

        return $erros;
    }
}
