<?php
/**
 * Script de Sincronização de Schema do Banco de Dados
 * Executa todos os schemas SQL necessários para o Admin Server
 * 
 * USO:
 *   Via CLI: php sync_schema.php
 *   Via Web: Acesse /database/sync_schema.php (requer autenticação)
 */

// Detectar se é CLI ou Web
$isCli = php_sapi_name() === 'cli';

// Se for web, verificar autenticação básica
if (!$isCli) {
    $validUser = 'admin';
    $validPass = 'sync2024!';
    
    if (!isset($_SERVER['PHP_AUTH_USER']) || 
        $_SERVER['PHP_AUTH_USER'] !== $validUser || 
        $_SERVER['PHP_AUTH_PW'] !== $validPass) {
        header('WWW-Authenticate: Basic realm="Schema Sync"');
        header('HTTP/1.0 401 Unauthorized');
        die('Autenticação necessária');
    }
    
    header('Content-Type: text/html; charset=utf-8');
    echo "<!DOCTYPE html><html><head><title>Schema Sync</title>";
    echo "<style>body{font-family:monospace;background:#1a1a2e;color:#eee;padding:20px}";
    echo ".success{color:#00ff88}.error{color:#ff4444}.warning{color:#ffaa00}";
    echo ".info{color:#00aaff}pre{background:#0d0d1a;padding:15px;border-radius:8px;overflow-x:auto}</style>";
    echo "</head><body><h1>🔄 Schema Sync</h1><pre>";
}

// Função para output
function out($msg, $type = 'info') {
    global $isCli;
    $colors = [
        'success' => "\033[32m",
        'error' => "\033[31m",
        'warning' => "\033[33m",
        'info' => "\033[36m",
        'reset' => "\033[0m"
    ];
    
    if ($isCli) {
        echo $colors[$type] . $msg . $colors['reset'] . "\n";
    } else {
        echo "<span class=\"{$type}\">" . htmlspecialchars($msg) . "</span>\n";
    }
}

/**
 * Parser de SQL que divide corretamente os statements
 */
function parseSqlStatements(string $sql): array {
    // Remover comentários de linha inteira
    $lines = explode("\n", $sql);
    $cleanLines = [];
    
    foreach ($lines as $line) {
        $trimmed = trim($line);
        // Pular linhas que são apenas comentários
        if (empty($trimmed) || strpos($trimmed, '--') === 0) {
            continue;
        }
        // Remover comentário no final da linha
        if (($pos = strpos($line, ' -- ')) !== false) {
            $line = substr($line, 0, $pos);
        }
        $cleanLines[] = $line;
    }
    
    $sql = implode("\n", $cleanLines);
    
    // Remover comentários de bloco
    $sql = preg_replace('/\/\*.*?\*\//s', '', $sql);
    
    // Dividir por ; mas respeitando DELIMITER
    $statements = [];
    $delimiter = ';';
    $buffer = '';
    
    $lines = explode("\n", $sql);
    foreach ($lines as $line) {
        $trimmed = trim($line);
        
        // Verificar mudança de DELIMITER
        if (preg_match('/^DELIMITER\s+(.+)$/i', $trimmed, $matches)) {
            $delimiter = trim($matches[1]);
            continue;
        }
        
        $buffer .= $line . "\n";
        
        // Verificar se termina com o delimiter atual
        if (str_ends_with(rtrim($buffer), $delimiter)) {
            $stmt = rtrim($buffer);
            // Remover o delimiter do final
            $stmt = substr($stmt, 0, -strlen($delimiter));
            $stmt = trim($stmt);
            
            if (!empty($stmt)) {
                $statements[] = $stmt;
            }
            $buffer = '';
        }
    }
    
    // Adicionar qualquer coisa restante no buffer
    $remaining = trim($buffer);
    if (!empty($remaining)) {
        $statements[] = $remaining;
    }
    
    return $statements;
}

out("╔════════════════════════════════════════════════════════════╗", 'info');
out("║          SINCRONIZAÇÃO DE SCHEMA DO BANCO DE DADOS         ║", 'info');
out("║                    Admin Server v2.0                       ║", 'info');
out("╚════════════════════════════════════════════════════════════╝", 'info');
out("");

// Carregar configuração do banco
require_once __DIR__ . '/../config/database.php';

try {
    out("📡 Conectando ao banco de dados...", 'info');
    $pdo = getDBConnection();
    out("✅ Conexão estabelecida com sucesso!", 'success');
    out("   Host: " . DB_HOST, 'info');
    out("   Database: " . DB_NAME, 'info');
    out("");
} catch (Exception $e) {
    out("❌ Erro ao conectar: " . $e->getMessage(), 'error');
    exit(1);
}

// Lista de schemas na ordem correta de execução
$schemas = [
    'schema.sql' => 'Schema Principal (users, sites, events, pix_config)',
    'schema_update_users.sql' => 'Atualização de Usuários (roles, permissions)',
    'schema_security_settings.sql' => 'Configurações de Segurança por Site',
    'schema_api_tokens.sql' => 'Gerenciamento de APIs Externas (tokens)',
];

$totalExecuted = 0;
$totalErrors = 0;
$totalSkipped = 0;

foreach ($schemas as $file => $description) {
    $filePath = __DIR__ . '/' . $file;
    
    out("─────────────────────────────────────────────────────────────", 'info');
    out("📄 {$file}", 'warning');
    out("   {$description}", 'info');
    
    if (!file_exists($filePath)) {
        out("   ⚠️  Arquivo não encontrado - PULANDO", 'warning');
        $totalSkipped++;
        continue;
    }
    
    $sql = file_get_contents($filePath);
    
    if (empty(trim($sql))) {
        out("   ⚠️  Arquivo vazio - PULANDO", 'warning');
        $totalSkipped++;
        continue;
    }
    
    $statements = parseSqlStatements($sql);
    $stmtCount = count($statements);
    out("   📊 {$stmtCount} statements encontrados", 'info');
    
    $stmtExecuted = 0;
    $stmtErrors = 0;
    
    foreach ($statements as $statement) {
        if (empty(trim($statement))) {
            continue;
        }
        
        try {
            $pdo->exec($statement);
            $stmtExecuted++;
            
            // Log de criação de tabela
            if (preg_match('/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?[`"]?(\w+)/i', $statement, $m)) {
                out("   ✓ Tabela: {$m[1]}", 'success');
            } elseif (preg_match('/ALTER\s+TABLE\s+[`"]?(\w+)/i', $statement, $m)) {
                out("   ✓ Alterado: {$m[1]}", 'success');
            }
            
        } catch (PDOException $e) {
            $errorMsg = $e->getMessage();
            
            // Erros que podemos ignorar (estrutura já existe)
            $ignorable = [
                'Duplicate column name',
                'Duplicate key name',
                'already exists',
                'check that column',
                'check that',
                'Duplicate entry',
                'Cannot add foreign key',
            ];
            
            $isIgnorable = false;
            foreach ($ignorable as $pattern) {
                if (stripos($errorMsg, $pattern) !== false) {
                    $isIgnorable = true;
                    break;
                }
            }
            
            if ($isIgnorable) {
                $stmtExecuted++;
                // Mostrar como info em vez de erro
                if (preg_match('/ALTER\s+TABLE\s+[`"]?(\w+)/i', $statement, $m)) {
                    out("   ≈ Já existe: {$m[1]} (OK)", 'info');
                }
            } else {
                out("   ❌ ERRO: " . substr($errorMsg, 0, 80), 'error');
                // Mostrar parte do statement que falhou
                $shortStmt = substr(trim($statement), 0, 60);
                out("      SQL: {$shortStmt}...", 'warning');
                $stmtErrors++;
            }
        }
    }
    
    if ($stmtErrors > 0) {
        out("   ⚠️  {$stmtExecuted}/{$stmtCount} executados, {$stmtErrors} erros", 'warning');
        $totalErrors++;
    } else {
        out("   ✅ {$stmtExecuted}/{$stmtCount} executados com sucesso", 'success');
        $totalExecuted++;
    }
}

out("");
out("═════════════════════════════════════════════════════════════", 'info');
out("                       📊 RESUMO FINAL", 'info');
out("═════════════════════════════════════════════════════════════", 'info');
out("  Schemas OK:         {$totalExecuted}", $totalExecuted > 0 ? 'success' : 'info');
out("  Schemas com erro:   {$totalErrors}", $totalErrors > 0 ? 'error' : 'info');
out("  Schemas pulados:    {$totalSkipped}", $totalSkipped > 0 ? 'warning' : 'info');
out("");

// Verificar tabelas existentes
out("📋 Tabelas no banco de dados:", 'info');
$tables = $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
out("   Total: " . count($tables) . " tabelas", 'info');
foreach ($tables as $table) {
    // Contar registros
    try {
        $count = $pdo->query("SELECT COUNT(*) FROM `{$table}`")->fetchColumn();
        out("   • {$table} ({$count} registros)", 'success');
    } catch (Exception $e) {
        out("   • {$table}", 'success');
    }
}

out("");
out("═════════════════════════════════════════════════════════════", 'info');

if ($totalErrors === 0) {
    out("✅ SINCRONIZAÇÃO CONCLUÍDA COM SUCESSO!", 'success');
    $exitCode = 0;
} else {
    out("⚠️  SINCRONIZAÇÃO CONCLUÍDA COM AVISOS", 'warning');
    $exitCode = 1;
}

out("═════════════════════════════════════════════════════════════", 'info');
out("📅 Data: " . date('d/m/Y H:i:s'), 'info');

if (!$isCli) {
    echo "</pre>";
    echo "<p><a href='javascript:location.reload()' style='color:#00aaff'>🔄 Executar novamente</a></p>";
    echo "</body></html>";
}

exit($exitCode);
