<?php
/**
 * CONFIGURAÇÃO DE BANCO DE DADOS
 * Checkout Pro 2025 - FASE 1: INFRAESTRUTURA
 * 
 * Versão Segura com:
 * - Caminhos absolutos via paths.php
 * - Credenciais via variáveis de ambiente (.env)
 * - Tratamento robusto de erros
 * - Prevenção de múltiplas conexões
 * 
 * @version 2.0
 * @author Checkout Pro 2025
 */

// Prevenir múltiplas inclusões do arquivo
if (defined('CONFIG_DB_LOADED')) {
    return; // Arquivo já foi carregado
}
define('CONFIG_DB_LOADED', true);

// Prevenir múltiplas inclusões e conexões duplicadas
if (isset($pdo) && $pdo instanceof PDO) {
    return; // Conexão já existe
}

// Carregar configuração de caminhos
if (!defined('ROOT_PATH')) {
    require_once __DIR__ . '/paths.php';
}

// Configuração de Fuso Horário
date_default_timezone_set('America/Sao_Paulo');
setlocale(LC_ALL, 'pt_BR', 'pt_BR.utf-8', 'portuguese');

// ============================================================
// CARREGAR VARIÁVEIS DE AMBIENTE (.env)
// ============================================================

/**
 * Carrega variáveis de ambiente do arquivo .env
 * Implementação simples sem dependência externa
 */
if (!function_exists('loadEnvFile')) {
    function loadEnvFile($envPath) {
        if (!file_exists($envPath)) {
            return false;
        }
        
        $lines = file($envPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        foreach ($lines as $line) {
            // Ignorar comentários
            if (strpos(trim($line), '#') === 0) {
                continue;
            }
            
            // Ignorar linhas sem =
            if (strpos($line, '=') === false) {
                continue;
            }
            
            list($key, $value) = explode('=', $line, 2);
            $key = trim($key);
            $value = trim($value);
            
            // Remover aspas se existirem
            $value = trim($value, '"\'');
            
            // Definir variável de ambiente se não existir
            if (!getenv($key)) {
                putenv("$key=$value");
                $_ENV[$key] = $value;
            }
        }
        
        return true;
    }
}

// Tentar carregar .env do diretório raiz
$envFile = ROOT_PATH . '/.env';
if (file_exists($envFile)) {
    loadEnvFile($envFile);
} else {
    // Log aviso (mas não bloqueia - pode usar getenv direto)
    error_log("AVISO: Arquivo .env não encontrado em " . $envFile . ". Usando variáveis de ambiente do sistema ou valores padrão.");
}

// ============================================================
// OBTER CREDENCIAIS DO BANCO DE DADOS
// ============================================================

// Prioridade: 1) Variáveis de ambiente (.env), 2) getenv(), 3) Valores padrão (apenas para desenvolvimento)
$host = getenv('DB_HOST') ?: ($_ENV['DB_HOST'] ?? 'localhost');
$dbname = getenv('DB_NAME') ?: ($_ENV['DB_NAME'] ?? '');
$username = getenv('DB_USER') ?: ($_ENV['DB_USER'] ?? '');
$password = getenv('DB_PASS') ?: ($_ENV['DB_PASS'] ?? '');

// Validação básica das credenciais
if (empty($dbname)) {
    error_log("ERRO CRÍTICO: DB_NAME não configurado. Verifique o arquivo .env ou variáveis de ambiente.");
    if (defined('APP_DEBUG') && APP_DEBUG === true) {
        die("Erro de configuração: Nome do banco de dados não foi definido. Configure DB_NAME no arquivo .env");
    } else {
        die("Erro de configuração do sistema. Contate o administrador.");
    }
}

if (empty($username)) {
    error_log("ERRO CRÍTICO: DB_USER não configurado. Verifique o arquivo .env ou variáveis de ambiente.");
    if (defined('APP_DEBUG') && APP_DEBUG === true) {
        die("Erro de configuração: Usuário do banco de dados não foi definido. Configure DB_USER no arquivo .env");
    } else {
        die("Erro de configuração do sistema. Contate o administrador.");
    }
}

// ============================================================
// CONEXÃO COM BANCO DE DADOS (PDO)
// ============================================================

$pdo = null;
$maxRetries = 3;
$retryDelay = 1; // segundos

for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
    try {
        // Construir DSN (Data Source Name)
        $dsn = "mysql:host={$host};dbname={$dbname};charset=utf8mb4";
        
        // Opções do PDO
        $options = [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false, // Usar prepared statements reais
            PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci",
            PDO::ATTR_PERSISTENT => false, // Não usar conexões persistentes (melhor para performance)
            PDO::ATTR_TIMEOUT => 5 // Timeout de 5 segundos
        ];
        
        // Tentar conexão
        $pdo = new PDO($dsn, $username, $password, $options);
        
        // Se chegou aqui, conexão foi bem-sucedida
        break;
        
    } catch (PDOException $e) {
        $errorCode = $e->getCode();
        $errorMessage = $e->getMessage();
        
        // Log detalhado do erro
        error_log("Tentativa {$attempt}/{$maxRetries} - Erro na conexão com banco de dados:");
        error_log("  Código: {$errorCode}");
        error_log("  Mensagem: {$errorMessage}");
        error_log("  Host: {$host}");
        error_log("  Database: {$dbname}");
        error_log("  Usuário: {$username}");
        
        // Se não for a última tentativa, aguardar antes de tentar novamente
        if ($attempt < $maxRetries) {
            sleep($retryDelay);
            continue;
        }
        
        // Se todas as tentativas falharam, tratar erro
        $pdo = null;
        
        // Determinar mensagem de erro apropriada
        $userMessage = "Erro de conexão com o banco de dados.";
        $debugMessage = $errorMessage;
        
        // Erros comuns e suas mensagens
        if ($errorCode == 1045) {
            $userMessage = "Erro de autenticação no banco de dados. Verifique usuário e senha.";
            $debugMessage = "Acesso negado para usuário '{$username}'";
        } elseif ($errorCode == 1049) {
            $userMessage = "Banco de dados '{$dbname}' não encontrado.";
            $debugMessage = "Database '{$dbname}' não existe";
        } elseif ($errorCode == 2002) {
            $userMessage = "Não foi possível conectar ao servidor de banco de dados.";
            $debugMessage = "Não foi possível conectar ao host '{$host}'";
        } elseif ($errorCode == 0 && strpos($errorMessage, 'Connection refused') !== false) {
            $userMessage = "Servidor de banco de dados recusou a conexão.";
            $debugMessage = "Conexão recusada pelo servidor";
        }
        
        // Log do erro final
        error_log("ERRO CRÍTICO: Falha na conexão com banco de dados após {$maxRetries} tentativas.");
        error_log("  Mensagem para usuário: {$userMessage}");
        error_log("  Mensagem técnica: {$debugMessage}");
        
        // Exibir erro apropriado
        http_response_code(500);
        
        // Em modo debug, mostrar mais detalhes
        if (defined('APP_DEBUG') && APP_DEBUG === true) {
            die("
                <h2>Erro de Conexão com Banco de Dados</h2>
                <p><strong>Mensagem:</strong> {$userMessage}</p>
                <p><strong>Detalhes Técnicos:</strong> {$debugMessage}</p>
                <p><strong>Código:</strong> {$errorCode}</p>
                <hr>
                <p><small>Este é um erro de debug. Em produção, apenas uma mensagem genérica será exibida.</small></p>
                <p><small>Verifique:</small></p>
                <ul>
                    <li>Arquivo .env existe e está configurado corretamente?</li>
                    <li>Credenciais do banco de dados estão corretas?</li>
                    <li>Servidor MySQL/MariaDB está rodando?</li>
                    <li>Host e porta estão acessíveis?</li>
                </ul>
            ");
        } else {
            // Em produção, mensagem genérica
            die("
                <h2>Erro do Sistema</h2>
                <p>Ocorreu um erro ao conectar com o banco de dados. Por favor, tente novamente mais tarde.</p>
                <p>Se o problema persistir, entre em contato com o suporte técnico.</p>
            ");
        }
    }
}

// Verificar se conexão foi estabelecida
if (!$pdo || !($pdo instanceof PDO)) {
    error_log("ERRO CRÍTICO: Variável \$pdo não foi inicializada corretamente.");
    http_response_code(500);
    die("Erro crítico do sistema. Contate o administrador.");
}

// Marcar conexão como estabelecida (para prevenir múltiplas conexões)
define('DB_CONNECTED', true);

// Log de sucesso (apenas em modo debug)
if (defined('APP_DEBUG') && APP_DEBUG === true) {
    error_log("✅ Conexão com banco de dados estabelecida com sucesso.");
    error_log("  Host: {$host}");
    error_log("  Database: {$dbname}");
    error_log("  Usuário: {$username}");
}

?>
