<?php
/**
 * auth.php — Sessão, login, controle de hierarquia e helpers de mensalidade.
 */

require_once __DIR__ . '/db_helper.php';

function iniciar_sessao_segura(): void
{
    if (session_status() === PHP_SESSION_NONE) {
        $config = db_read('config');
        $tempo = ($config['seguranca']['tempo_sessao_minutos'] ?? 120) * 60;

        session_set_cookie_params([
            'lifetime' => $tempo,
            'path' => '/',
            'httponly' => true,
            'samesite' => 'Lax',
            // 'secure' => true, // ativar quando estiver em produção com HTTPS
        ]);
        session_start();

        // Expiração por inatividade
        if (isset($_SESSION['ultimo_acesso']) && (time() - $_SESSION['ultimo_acesso'] > $tempo)) {
            session_unset();
            session_destroy();
            session_start();
        }
        $_SESSION['ultimo_acesso'] = time();
    }
}

function usuario_logado(): ?array
{
    iniciar_sessao_segura();
    $usuario = $_SESSION['usuario'] ?? null;

    // Proteção contra sessão antiga/corrompida (de uma versão anterior do
    // sistema que guardava outra coisa em $_SESSION['usuario'], por
    // exemplo). Em vez de quebrar com erro fatal, limpa e força novo login.
    if ($usuario !== null && !is_array($usuario)) {
        session_unset();
        session_destroy();
        return null;
    }

    return $usuario;
}

function exigir_login(): array
{
    $u = usuario_logado();
    if (!$u) {
        header('Location: index.php');
        exit;
    }
    return $u;
}

/**
 * Só permite acesso se o nível do usuário estiver na lista de níveis permitidos.
 */
function exigir_nivel(array $niveisPermitidos): array
{
    $u = exigir_login();
    if (!in_array($u['nivel'], $niveisPermitidos, true)) {
        http_response_code(403);
        die('Acesso negado: seu nível de usuário não tem permissão para esta ação.');
    }
    return $u;
}

function tentar_login(string $usuario, string $senha): array
{
    $usuarios = db_read('usuarios');
    foreach ($usuarios as $u) {
        if (strcasecmp($u['usuario'], $usuario) === 0) {
            if (!($u['ativo'] ?? true)) {
                return ['ok' => false, 'msg' => 'Usuário inativo. Contate o administrador.'];
            }
            if ($u['nivel'] !== 'ADM' && !empty($u['vencimento_painel'])) {
                $hoje = new DateTime('today');
                $venc = new DateTime($u['vencimento_painel']);
                $diff = (int) $hoje->diff($venc)->format('%r%a'); // negativo = vencido
                if ($diff < -5) {
                    return ['ok' => false, 'msg' => 'Sua mensalidade de acesso ao painel está vencida. Contate quem administra sua conta para renovar.'];
                }
            }
            if (password_verify($senha, $u['senha_hash'])) {
                iniciar_sessao_segura();
                unset($u['senha_hash']);
                $_SESSION['usuario'] = $u;
                auditoria_log($u['usuario'], 'LOGIN', 'Login realizado com sucesso.');
                return ['ok' => true];
            }
            auditoria_log($usuario, 'LOGIN_FALHOU', 'Senha incorreta.');
            return ['ok' => false, 'msg' => 'Usuário ou senha inválidos.'];
        }
    }
    return ['ok' => false, 'msg' => 'Usuário ou senha inválidos.'];
}

function fazer_logout(): void
{
    iniciar_sessao_segura();
    if (isset($_SESSION['usuario'])) {
        auditoria_log($_SESSION['usuario']['usuario'], 'LOGOUT', '');
    }
    session_unset();
    session_destroy();
}

/**
 * Retorna os IDs de todos os usuários "abaixo" na hierarquia (para escopo
 * de dashboards e listagens: Revenda vê sub-revendas e clientes delas, etc.)
 */
function ids_subordinados(string $idUsuario): array
{
    $usuarios = db_read('usuarios');
    $diretos = array_values(array_filter($usuarios, fn($u) => ($u['criado_por'] ?? null) === $idUsuario));
    $todos = array_map(fn($u) => $u['id'], $diretos);
    foreach ($diretos as $d) {
        $todos = array_merge($todos, ids_subordinados($d['id']));
    }
    return $todos;
}

/** IDs visíveis para o usuário (ele mesmo + subordinados). ADM vê tudo (retorna null = sem filtro). */
function escopo_visibilidade(array $usuarioLogado): ?array
{
    if ($usuarioLogado['nivel'] === 'ADM') {
        return null; // null = sem restrição, vê tudo
    }
    return array_merge([$usuarioLogado['id']], ids_subordinados($usuarioLogado['id']));
}

/**
 * Renova (soma meses a) a mensalidade de acesso ao painel de um usuário
 * Revenda/Sub-Revenda. Usado pelo ADM (para Revendas) ou pela Revenda
 * (para suas Sub-Revendas) — sem sistema de créditos, é assinatura mensal.
 */
function renovar_mensalidade_painel(string $idUsuario, int $meses): ?array
{
    return db_update('usuarios', function (&$usuarios) use ($idUsuario, $meses) {
        foreach ($usuarios as &$u) {
            if ($u['id'] === $idUsuario) {
                $base = new DateTime($u['vencimento_painel'] ?? 'today');
                if ($base < new DateTime('today')) {
                    $base = new DateTime('today');
                }
                $base->modify("+{$meses} months");
                $u['vencimento_painel'] = $base->format('Y-m-d');
                $u['ativo'] = true;
                $r = $u;
                unset($r['senha_hash']);
                return $r;
            }
        }
        return null;
    });
}
