<?php

require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../config/log.php';

class Usuario
{
    private $pdo;

    public function __construct()
    {
        try {
            $this->pdo = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME, DB_USER, DB_PASS);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            die("Erro na conexão com o banco de dados: " . $e->getMessage());
        }
    }

    public function salvarTokenGoogle($idUsuario, $tokenJson)
    {
        $sql = "UPDATE usuarios SET google_auth_token = :token WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        return $stmt->execute([
            ':token' => $tokenJson,
            ':id' => $idUsuario
        ]);
    }

    public function getTokenGoogle($idUsuario)
    {
        $sql = "SELECT google_auth_token FROM usuarios WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':id' => $idUsuario]);
        $resultado = $stmt->fetch(PDO::FETCH_ASSOC);
        return $resultado ? $resultado['google_auth_token'] : null;
    }

    public function findByEmail($email)
    {
        $stmt = $this->pdo->prepare("SELECT * FROM usuarios WHERE email = :email AND ativo = 1");
        $stmt->execute(['email' => $email]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    public function createUser($email, $password)
    {
        $hashedPassword = password_hash($password, PASSWORD_BCRYPT);
        $stmt = $this->pdo->prepare("INSERT INTO usuarios (email, senha, ativo) VALUES (:email, :senha, 1)");
        try {
            $stmt->execute(['email' => $email, 'senha' => $hashedPassword]);
            return true;
        } catch (PDOException $e) {
            return false;
        }
    }

    public function verificarLogin($email, $senhaDigitada)
    {
        Logger::log("Iniciando verificação de login para e-mail: " . $email);
        $usuario = $this->findByEmail($email);
        if (!$usuario) {
            Logger::log("Usuário não encontrado para o e-mail: " . $email);
            return false;
        }
        $hashSalvoNoBanco = $usuario['senha'];
        if (password_verify($senhaDigitada, $hashSalvoNoBanco)) {
            Logger::log("Senha verificada com sucesso para o usuário: " . $email);
            return $usuario;
        } else {
            Logger::log("Senha incorreta para o usuário: " . $email);
            return false;
        }
    }

    // NOVOS MÉTODOS PARA O PAINEL ADMIN

    public function getAll()
    {
        $stmt = $this->pdo->query("SELECT id, nome, email, nivel_acesso, ativo, data_criacao FROM usuarios ORDER BY data_criacao DESC");
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function criar($nome, $email, $senha, $nivelAcesso)
    {
        try {
            // Verificar se o email já existe
            $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM usuarios WHERE email = :email");
            $stmt->execute(['email' => $email]);

            if ($stmt->fetchColumn() > 0) {
                return false; // Email já existe
            }

            $hashedPassword = password_hash($senha, PASSWORD_BCRYPT);
            $stmt = $this->pdo->prepare("INSERT INTO usuarios (nome, email, senha, nivel_acesso, ativo) VALUES (:nome, :email, :senha, :nivel_acesso, 1)");
            return $stmt->execute([
                'nome' => $nome,
                'email' => $email,
                'senha' => $hashedPassword,
                'nivel_acesso' => $nivelAcesso
            ]);
        } catch (PDOException $e) {
            return false;
        }
    }

    public function findById($id)
    {
        $stmt = $this->pdo->prepare("SELECT * FROM usuarios WHERE id = :id");
        $stmt->execute(['id' => $id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    public function toggleStatus($id)
    {
        $stmt = $this->pdo->prepare("UPDATE usuarios SET ativo = NOT ativo WHERE id = :id");
        return $stmt->execute(['id' => $id]);
    }

    // MÉTODOS PARA SISTEMA DE PERMISSÕES

    public function getPermissoes($nivelAcesso)
    {
        $stmt = $this->pdo->prepare("SELECT modulo, pode_visualizar, pode_criar, pode_editar, pode_excluir FROM niveis_acesso_permissoes WHERE nivel_acesso = :nivel_acesso");
        $stmt->execute(['nivel_acesso' => $nivelAcesso]);
        $permissoes = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // Organizar permissões por módulo
        $permissoesOrganizadas = [];
        foreach ($permissoes as $permissao) {
            $permissoesOrganizadas[$permissao['modulo']] = [
                'visualizar' => (bool) $permissao['pode_visualizar'],
                'criar' => (bool) $permissao['pode_criar'],
                'editar' => (bool) $permissao['pode_editar'],
                'excluir' => (bool) $permissao['pode_excluir']
            ];
        }

        return $permissoesOrganizadas;
    }

    public function temPermissao($nivelAcesso, $modulo, $acao = 'visualizar')
    {
        // Mapear ações para colunas da tabela
        $colunaMap = [
            'visualizar' => 'pode_visualizar',
            'criar' => 'pode_criar',
            'editar' => 'pode_editar',
            'excluir' => 'pode_excluir'
        ];

        $coluna = $colunaMap[$acao] ?? 'pode_visualizar';

        $stmt = $this->pdo->prepare("SELECT $coluna FROM niveis_acesso_permissoes WHERE nivel_acesso = :nivel_acesso AND modulo = :modulo");
        $stmt->execute(['nivel_acesso' => $nivelAcesso, 'modulo' => $modulo]);
        $resultado = $stmt->fetch(PDO::FETCH_ASSOC);

        return $resultado ? (bool) $resultado[$coluna] : false;
    }

    public function getNiveisAcesso()
    {
        return [
            'Admin' => 'Administrador (Acesso Total + Configurações)',
            'Acesso_Total' => 'Acesso Total (Todos os Módulos)',
            'Agenda_Financeiro_Documentos' => 'Agenda + Financeiro + Documentos',
            'Eleitor_Documentos' => 'Eleitores + Documentos',
            'Documentos_Financeiro_RH' => 'Documentos + Financeiro + RH',
            'Eleitor' => 'Eleitor'
        ];
    }

    /**
     * Conta quantos usuários existem por nível de acesso
     */
    public function contarUsuariosPorNivel($nivel)
    {
        try {
            $stmt = $this->pdo->prepare("SELECT COUNT(*) as total FROM usuarios WHERE nivel_acesso = ? AND ativo = 1");
            $stmt->execute([$nivel]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result['total'] ?? 0;
        } catch (PDOException $e) {
            error_log("Erro ao contar usuários por nível: " . $e->getMessage());
            return 0;
        }
    }

    /**
     * Atualiza o nível de acesso de um usuário
     */
    public function atualizarNivelAcesso($usuarioId, $novoNivel)
    {
        try {
            $stmt = $this->pdo->prepare("UPDATE usuarios SET nivel_acesso = ? WHERE id = ?");
            return $stmt->execute([$novoNivel, $usuarioId]);
        } catch (PDOException $e) {
            error_log("Erro ao atualizar nível de acesso: " . $e->getMessage());
            return false;
        }
    }

    public function atualizarUsuario(int $id, string $nome, string $email, string $nivelAcesso, ?string $senha = null): bool
    {
        try {
            // Verificar se o email já está em uso por outro usuário
            $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM usuarios WHERE email = :email AND id <> :id");
            $stmt->execute([':email' => $email, ':id' => $id]);
            if ((int) $stmt->fetchColumn() > 0) {
                return false;
            }

            $sql = "UPDATE usuarios SET nome = :nome, email = :email, nivel_acesso = :nivel_acesso";
            $params = [
                ':nome' => $nome,
                ':email' => $email,
                ':nivel_acesso' => $nivelAcesso,
                ':id' => $id
            ];

            if (!empty($senha)) {
                $hashed = password_hash($senha, PASSWORD_BCRYPT);
                $sql .= ", senha = :senha";
                $params[':senha'] = $hashed;
            }

            $sql .= " WHERE id = :id";
            $stmt = $this->pdo->prepare($sql);
            return $stmt->execute($params);
        } catch (PDOException $e) {
            error_log("Erro ao atualizar usuário: " . $e->getMessage());
            return false;
        }
    }

    // Listagem com filtros e paginação
    public function getAllFiltered($q = '', $nivel = '', $status = '', $offset = 0, $limit = 10, $sortBy = 'data_criacao', $sortDir = 'DESC')
    {
        $allowedSort = ['id', 'nome', 'email', 'nivel_acesso', 'ativo', 'data_criacao'];
        $sortBy = in_array($sortBy, $allowedSort) ? $sortBy : 'data_criacao';
        $sortDir = strtoupper($sortDir) === 'ASC' ? 'ASC' : 'DESC';

        $where = [];
        $params = [];

        if (!empty($q)) {
            $where[] = '(nome LIKE :q OR email LIKE :q)';
            $params[':q'] = '%' . $q . '%';
        }
        if (!empty($nivel)) {
            $where[] = 'nivel_acesso = :nivel';
            $params[':nivel'] = $nivel;
        }
        if ($status !== '') {
            if ($status === 'ativo' || $status === 'inativo') {
                $where[] = 'ativo = :ativo';
                $params[':ativo'] = ($status === 'ativo') ? 1 : 0;
            }
        }

        $sql = 'SELECT id, nome, email, nivel_acesso, ativo, data_criacao FROM usuarios';
        if (count($where) > 0) {
            $sql .= ' WHERE ' . implode(' AND ', $where);
        }
        $sql .= " ORDER BY $sortBy $sortDir LIMIT :limit OFFSET :offset";

        $stmt = $this->pdo->prepare($sql);
        foreach ($params as $key => $value) {
            $stmt->bindValue($key, $value);
        }
        $stmt->bindValue(':limit', (int) $limit, PDO::PARAM_INT);
        $stmt->bindValue(':offset', (int) $offset, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function getFilteredCount($q = '', $nivel = '', $status = '')
    {
        $where = [];
        $params = [];

        if (!empty($q)) {
            $where[] = '(nome LIKE :q OR email LIKE :q)';
            $params[':q'] = '%' . $q . '%';
        }
        if (!empty($nivel)) {
            $where[] = 'nivel_acesso = :nivel';
            $params[':nivel'] = $nivel;
        }
        if ($status !== '') {
            if ($status === 'ativo' || $status === 'inativo') {
                $where[] = 'ativo = :ativo';
                $params[':ativo'] = ($status === 'ativo') ? 1 : 0;
            }
        }

        $sql = 'SELECT COUNT(*) as total FROM usuarios';
        if (count($where) > 0) {
            $sql .= ' WHERE ' . implode(' AND ', $where);
        }

        $stmt = $this->pdo->prepare($sql);
        foreach ($params as $key => $value) {
            $stmt->bindValue($key, $value);
        }
        $stmt->execute();
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        return (int) ($result['total'] ?? 0);
    }

    public function getDistinctNiveis()
    {
        $stmt = $this->pdo->query("SELECT DISTINCT nivel_acesso FROM usuarios WHERE nivel_acesso IS NOT NULL AND nivel_acesso <> '' ORDER BY nivel_acesso ASC");
        return $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
    }
}
