<?php
/*
desenvolvedor: luciano donizeti
mania de script: www.maniadescript.com.br
whatsapp 43998240911
*/

/**
 * Controle de limite diário para geração dos banners de jogos do dia.
 * Versão compatível com hospedagens que usam PHP mais antigo.
 */

date_default_timezone_set('America/Sao_Paulo');

if (!function_exists('limiteGeracoesDebug')) {
    function limiteGeracoesDebug($message) {
        @error_log(date('Y-m-d H:i:s') . ' - ' . $message . "\n", 3, __DIR__ . '/session_debug.log');
    }
}

if (!function_exists('limiteGeracoesPdo')) {
    function limiteGeracoesPdo() {
        require_once __DIR__ . '/db/configdb.php';
        return new PDO(
            "mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=utf8mb4",
            DB_USER,
            DB_PASS,
            array(
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                PDO::ATTR_EMULATE_PREPARES => false
            )
        );
    }
}

if (!function_exists('limiteGeracoesEnsureSchema')) {
    function limiteGeracoesEnsureSchema($pdo) {
        try {
            $stmt = $pdo->query("SHOW COLUMNS FROM usuarios LIKE 'limite_geracoes_dia'");
            if (!$stmt->fetch()) {
                $stmtAfter = $pdo->query("SHOW COLUMNS FROM usuarios LIKE 'tema_painel'");
                if ($stmtAfter->fetch()) {
                    $afterSql = " AFTER tema_painel";
                } else {
                    $stmtAfterBloqueio = $pdo->query("SHOW COLUMNS FROM usuarios LIKE 'bloquear_credenciais'");
                    $afterSql = $stmtAfterBloqueio->fetch() ? " AFTER bloquear_credenciais" : "";
                }
                $pdo->exec("ALTER TABLE usuarios ADD COLUMN limite_geracoes_dia INT NOT NULL DEFAULT 0 COMMENT '0=ilimitado; limite diario de geracoes de jogos do dia'" . $afterSql);
            }

            $pdo->exec("CREATE TABLE IF NOT EXISTS geracoes_jogos_dia (
                id INT NOT NULL AUTO_INCREMENT,
                usuario_id INT NOT NULL,
                data_ref DATE NOT NULL,
                total INT NOT NULL DEFAULT 0,
                criado_em DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                atualizado_em DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                PRIMARY KEY (id),
                UNIQUE KEY uniq_usuario_data (usuario_id, data_ref),
                KEY idx_data_ref (data_ref)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
        } catch (Exception $e) {
            limiteGeracoesDebug('Erro ao garantir schema de limite de geracoes: ' . $e->getMessage());
        }
    }
}

if (!function_exists('limiteGeracoesNormalizarLimite')) {
    function limiteGeracoesNormalizarLimite($valor) {
        $limite = (int)$valor;
        if ($limite < 0) { $limite = 0; }
        if ($limite > 9999) { $limite = 9999; }
        return $limite;
    }
}

if (!function_exists('limiteGeracoesUsuario')) {
    function limiteGeracoesUsuario($pdo, $usuarioId) {
        limiteGeracoesEnsureSchema($pdo);
        $stmt = $pdo->prepare("SELECT id, nivel, COALESCE(limite_geracoes_dia, 0) AS limite_geracoes_dia FROM usuarios WHERE id = ? LIMIT 1");
        $stmt->execute(array($usuarioId));
        $user = $stmt->fetch();
        return $user ? $user : null;
    }
}

if (!function_exists('limiteGeracoesStatus')) {
    function limiteGeracoesStatus($pdo, $usuarioId) {
        limiteGeracoesEnsureSchema($pdo);
        $data = date('Y-m-d');
        $user = limiteGeracoesUsuario($pdo, $usuarioId);
        if (!$user) {
            return array(
                'ok' => false,
                'bloqueado' => true,
                'mensagem' => 'Usuário não encontrado para validar limite diário.',
                'limite' => 0,
                'usado' => 0,
                'restante' => 0,
                'ilimitado' => false,
                'data' => $data
            );
        }

        $limite = limiteGeracoesNormalizarLimite(isset($user['limite_geracoes_dia']) ? $user['limite_geracoes_dia'] : 0);
        $nivel = (int)(isset($user['nivel']) ? $user['nivel'] : 3);

        $stmt = $pdo->prepare("SELECT total FROM geracoes_jogos_dia WHERE usuario_id = ? AND data_ref = ? LIMIT 1");
        $stmt->execute(array($usuarioId, $data));
        $usado = (int)($stmt->fetchColumn() ? $stmt->fetchColumn() : 0);
        // fetchColumn foi chamado acima; refaz a leitura para evitar perda em hospedagens antigas.
        $stmt = $pdo->prepare("SELECT total FROM geracoes_jogos_dia WHERE usuario_id = ? AND data_ref = ? LIMIT 1");
        $stmt->execute(array($usuarioId, $data));
        $valorTotal = $stmt->fetchColumn();
        $usado = (int)($valorTotal ? $valorTotal : 0);

        $ilimitado = ($nivel === 1 || $limite === 0);
        $restante = $ilimitado ? null : max(0, $limite - $usado);

        return array(
            'ok' => true,
            'bloqueado' => (!$ilimitado && $usado >= $limite),
            'mensagem' => (!$ilimitado && $usado >= $limite)
                ? 'Limite diário de geração de jogos do dia atingido. Fale com o administrador.'
                : 'Geração liberada.',
            'limite' => $limite,
            'usado' => $usado,
            'restante' => $restante,
            'ilimitado' => $ilimitado,
            'data' => $data
        );
    }
}

if (!function_exists('limiteGeracoesConsumir')) {
    function limiteGeracoesConsumir($pdo, $usuarioId, $quantidade = 1) {
        limiteGeracoesEnsureSchema($pdo);
        $quantidade = max(1, (int)$quantidade);
        $data = date('Y-m-d');

        try {
            $pdo->beginTransaction();

            $stmt = $pdo->prepare("SELECT id, nivel, COALESCE(limite_geracoes_dia, 0) AS limite_geracoes_dia FROM usuarios WHERE id = ? LIMIT 1 FOR UPDATE");
            $stmt->execute(array($usuarioId));
            $user = $stmt->fetch();
            if (!$user) {
                $pdo->rollBack();
                return array(
                    'ok' => false,
                    'bloqueado' => true,
                    'mensagem' => 'Usuário não encontrado para validar limite diário.',
                    'limite' => 0,
                    'usado' => 0,
                    'restante' => 0,
                    'ilimitado' => false,
                    'data' => $data
                );
            }

            $nivel = (int)(isset($user['nivel']) ? $user['nivel'] : 3);
            $limite = limiteGeracoesNormalizarLimite(isset($user['limite_geracoes_dia']) ? $user['limite_geracoes_dia'] : 0);

            if ($nivel === 1 || $limite === 0) {
                $pdo->commit();
                $status = limiteGeracoesStatus($pdo, $usuarioId);
                $status['consumido'] = 0;
                return $status;
            }

            $stmt = $pdo->prepare("SELECT id, total FROM geracoes_jogos_dia WHERE usuario_id = ? AND data_ref = ? LIMIT 1 FOR UPDATE");
            $stmt->execute(array($usuarioId, $data));
            $row = $stmt->fetch();
            $usadoAtual = $row ? (int)$row['total'] : 0;

            if (($usadoAtual + $quantidade) > $limite) {
                $pdo->rollBack();
                return array(
                    'ok' => false,
                    'bloqueado' => true,
                    'mensagem' => 'Limite diário de geração de jogos do dia atingido. Fale com o administrador.',
                    'limite' => $limite,
                    'usado' => $usadoAtual,
                    'restante' => max(0, $limite - $usadoAtual),
                    'ilimitado' => false,
                    'data' => $data,
                    'consumido' => 0
                );
            }

            $novoTotal = $usadoAtual + $quantidade;
            if ($row) {
                $stmt = $pdo->prepare("UPDATE geracoes_jogos_dia SET total = ?, atualizado_em = NOW() WHERE id = ?");
                $stmt->execute(array($novoTotal, (int)$row['id']));
            } else {
                $stmt = $pdo->prepare("INSERT INTO geracoes_jogos_dia (usuario_id, data_ref, total) VALUES (?, ?, ?)");
                $stmt->execute(array($usuarioId, $data, $novoTotal));
            }

            $pdo->commit();
            return array(
                'ok' => true,
                'bloqueado' => false,
                'mensagem' => 'Geração liberada.',
                'limite' => $limite,
                'usado' => $novoTotal,
                'restante' => max(0, $limite - $novoTotal),
                'ilimitado' => false,
                'data' => $data,
                'consumido' => $quantidade
            );
        } catch (Exception $e) {
            if ($pdo->inTransaction()) { $pdo->rollBack(); }
            limiteGeracoesDebug('Erro ao consumir limite de geracoes: ' . $e->getMessage());
            return array(
                'ok' => false,
                'bloqueado' => true,
                'mensagem' => 'Erro ao validar limite diário. Tente novamente.',
                'limite' => 0,
                'usado' => 0,
                'restante' => 0,
                'ilimitado' => false,
                'data' => $data
            );
        }
    }
}

if (!function_exists('limiteGeracoesGrantKey')) {
    function limiteGeracoesGrantKey($usuarioId, $day, $modelo) {
        $day = preg_replace('/[^a-z0-9_-]/i', '', strtolower($day ? $day : 'hoje'));
        if (!$day) { $day = 'hoje'; }
        $modelo = preg_replace('/[^a-z0-9_-]/i', '', strtolower($modelo ? $modelo : 'modelo'));
        if (!$modelo) { $modelo = 'modelo'; }
        return $usuarioId . '|' . date('Y-m-d') . '|' . $day . '|' . $modelo;
    }
}

if (!function_exists('limiteGeracoesTemGrant')) {
    function limiteGeracoesTemGrant($usuarioId, $day = 'hoje', $modelo = 'modelo') {
        $key = limiteGeracoesGrantKey($usuarioId, $day, $modelo);
        return isset($_SESSION['geracoes_jogos_grants'][$key]) && $_SESSION['geracoes_jogos_grants'][$key] === date('Y-m-d');
    }
}

if (!function_exists('limiteGeracoesAdicionarGrant')) {
    function limiteGeracoesAdicionarGrant($usuarioId, $day = 'hoje', $modelo = 'modelo') {
        if (!isset($_SESSION['geracoes_jogos_grants']) || !is_array($_SESSION['geracoes_jogos_grants'])) {
            $_SESSION['geracoes_jogos_grants'] = array();
        }
        $_SESSION['geracoes_jogos_grants'][limiteGeracoesGrantKey($usuarioId, $day, $modelo)] = date('Y-m-d');
    }
}

if (!function_exists('limiteGeracoesConsumirComGrant')) {
    function limiteGeracoesConsumirComGrant($usuarioId, $day = 'hoje', $modelo = 'modelo') {
        $pdo = limiteGeracoesPdo();
        limiteGeracoesEnsureSchema($pdo);

        if (limiteGeracoesTemGrant($usuarioId, $day, $modelo)) {
            $status = limiteGeracoesStatus($pdo, $usuarioId);
            $status['grant_existente'] = true;
            return $status;
        }

        $status = limiteGeracoesConsumir($pdo, $usuarioId, 1);
        if (!empty($status['ok']) && empty($status['bloqueado'])) {
            limiteGeracoesAdicionarGrant($usuarioId, $day, $modelo);
        }
        return $status;
    }
}

if (!function_exists('limiteGeracoesStatusPorUsuarioId')) {
    function limiteGeracoesStatusPorUsuarioId($usuarioId) {
        try {
            $pdo = limiteGeracoesPdo();
            return limiteGeracoesStatus($pdo, $usuarioId);
        } catch (Exception $e) {
            limiteGeracoesDebug('Erro ao consultar status por usuario: ' . $e->getMessage());
            return array(
                'ok' => false,
                'bloqueado' => false,
                'mensagem' => 'Não foi possível consultar o limite diário.',
                'limite' => 0,
                'usado' => 0,
                'restante' => null,
                'ilimitado' => true,
                'data' => date('Y-m-d')
            );
        }
    }
}

if (!function_exists('limiteGeracoesMensagemHtml')) {
    function limiteGeracoesMensagemHtml($status, $classe = 'info') {
        $classe = in_array($classe, array('success','danger','warning','info'), true) ? $classe : 'info';
        if (!empty($status['ilimitado'])) {
            $texto = 'Limite diário: ilimitado.';
        } else {
            $texto = 'Limite diário: ' . (int)(isset($status['usado']) ? $status['usado'] : 0) . ' de ' . (int)(isset($status['limite']) ? $status['limite'] : 0) . ' gerações usadas hoje.';
            $texto .= ' Restantes: ' . (int)(isset($status['restante']) ? $status['restante'] : 0) . '.';
        }
        return '<div class="alert alert-' . $classe . ' text-center">' . htmlspecialchars($texto, ENT_QUOTES, 'UTF-8') . '</div>';
    }
}

if (!function_exists('limiteGeracoesOutputImagemBloqueio')) {
    function limiteGeracoesOutputImagemBloqueio($mensagem) {
        while (ob_get_level()) { @ob_end_clean(); }
        if (!function_exists('imagecreatetruecolor')) {
            header('Content-Type: text/plain; charset=utf-8');
            echo $mensagem;
            exit;
        }
        header('Content-Type: image/png');
        $w = 1200; $h = 360;
        $im = imagecreatetruecolor($w, $h);
        $bg = imagecolorallocate($im, 20, 24, 39);
        $fg = imagecolorallocate($im, 255, 255, 255);
        $warn = imagecolorallocate($im, 245, 158, 11);
        imagefilledrectangle($im, 0, 0, $w, $h, $bg);
        imagestring($im, 5, 40, 80, 'Geracao bloqueada', $warn);
        $linhas = str_split($mensagem, 90);
        $y = 135;
        foreach ($linhas as $linha) {
            imagestring($im, 4, 40, $y, $linha, $fg);
            $y += 24;
        }
        imagestring($im, 3, 40, $h - 60, 'Acesse o administrador para aumentar o limite diario deste revendedor.', $fg);
        imagepng($im);
        imagedestroy($im);
        exit;
    }
}

if (!function_exists('limiteGeracoesValidarAcessoGerador')) {
    function limiteGeracoesValidarAcessoGerador($modelo) {
        if (!isset($_SESSION['user_id'])) {
            limiteGeracoesOutputImagemBloqueio('Sessao expirada. Faca login novamente.');
        }
        $usuarioId = (int)$_SESSION['user_id'];
        $day = isset($_GET['day']) ? (string)$_GET['day'] : 'hoje';
        if (limiteGeracoesTemGrant($usuarioId, $day, $modelo)) {
            return;
        }
        $status = limiteGeracoesConsumirComGrant($usuarioId, $day, $modelo);
        if (empty($status['ok']) || !empty($status['bloqueado'])) {
            limiteGeracoesOutputImagemBloqueio(isset($status['mensagem']) ? $status['mensagem'] : 'Limite diario atingido.');
        }
    }
}
?>
