<?php
session_start();
header('Content-Type: text/html; charset=UTF-8');
// Akışlı çıktı için tamponlamayı azalt
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no'); // Nginx uyumluluğu
@ini_set('output_buffering', 'off');
@ini_set('zlib.output_compression', '0');
@ini_set('implicit_flush', '1');
ob_implicit_flush(true);

function stream_echo($html) {
    echo $html, "\n";
    // Bazı sunucularda flush’ı tetiklemek için küçük bir tampon
    echo str_repeat(' ', 64);
    if (function_exists('ob_flush')) { @ob_flush(); }
    flush();
}

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

if (!isset($_SESSION['admin_logged_in'])) {
    http_response_code(403);
    echo '<p>Erişim yok</p>';
    exit;
}

$limit = isset($_GET['limit']) ? max(1, (int)$_GET['limit']) : 50;
$dry   = isset($_GET['dry']) ? (int)$_GET['dry'] === 1 : false;
$force = isset($_GET['force']) ? (int)$_GET['force'] === 1 : false;
$cols  = isset($_GET['cols']) ? explode(',', $_GET['cols']) : ['cover','banner'];
$cols  = array_values(array_intersect($cols, ['cover','banner']));
if (!$cols) { $cols = ['cover','banner']; }

// Base URL sadece atlama kontrolü için kullanılır; DB'ye 'images/...' yazacağız
$baseUrl = isset($_GET['base']) && preg_match('#^https?://#i', $_GET['base']) ? $_GET['base'] : 'https://blackbet1.com';
$baseUrl = rtrim($baseUrl, '/');

$docRoot = realpath(__DIR__ . '/../../');
$imagesRootRel = '/images';
if ($docRoot === false) {
    echo '<p>Doküman kökü bulunamadı.</p>';
    exit;
}

function is_http_url($val) {
    return is_string($val) && preg_match('#^https?://#i', $val);
}

function curl_download($url) {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_CONNECTTIMEOUT => 8,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_USERAGENT => 'BlackbetAdmin/1.0',
    ]);
    $data = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $err = curl_error($ch);
    curl_close($ch);
    if ($data === false || $status >= 400) {
        return [false, "HTTP $status $err"];
    }
    return [true, $data];
}

// IO'yu azaltmak için http ile başlayan kayıtları çek ve LIMIT uygula
$stmt = $pdo->query("SELECT id, game_name, cover, banner FROM games 
    WHERE cover LIKE 'http%' OR banner LIKE 'http%'
    ORDER BY id DESC LIMIT " . (int)$limit);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

$processed = 0; $downloaded = 0; $updated = 0; $skipped = 0; $errors = [];
$logs = [];

// Akış başlangıcı bilgisi
stream_echo('<div><strong>Görsel aynalama başlatıldı</strong> — limit: ' . htmlspecialchars((string)$limit) . ', kolonlar: <code>' . htmlspecialchars(implode(',', $cols)) . '</code></div>');

// İşleri çıkar: her satır/kolon için görev listesi
$tasks = [];
$rowsIndex = [];
foreach ($rows as $row) {
    $id = (int)$row['id'];
    $name = $row['game_name'];
    $rowsIndex[$id] = ['name' => $name, 'changes' => [], 'msgs' => []];
    foreach ($cols as $col) {
        $val = $row[$col] ?? '';
        if (!is_http_url($val)) { $skipped++; $rowsIndex[$id]['msgs'][] = $col . ' atlandı (http değil)'; continue; }
        // Zaten images yoluysa işlem yapma
        if (stripos($val, '/images/') === 0 || stripos($val, 'images/') === 0) { $skipped++; $rowsIndex[$id]['msgs'][] = $col . ' atlandı (zaten images)'; continue; }
        $path = parse_url($val, PHP_URL_PATH);
        if (!$path) { $errors[] = "id#$id $col geçersiz path: $val"; $rowsIndex[$id]['msgs'][] = $col . ' hata (geçersiz path)'; continue; }
        $cleanPath = '/' . ltrim($path, '/');
        $relPath = $imagesRootRel . $cleanPath;
        $targetAbs = $docRoot . $relPath;
        $imagesRootAbs = $docRoot . $imagesRootRel;
        $normTarget = str_replace('\\', '/', $targetAbs);
        $normImagesRoot = str_replace('\\', '/', $imagesRootAbs);
        if (strpos($normTarget, $normImagesRoot) !== 0) { $errors[] = "id#$id $col güvenlik nedeniyle reddedildi (hedef /images dışında): $relPath"; continue; }
        // Dosya zaten varsa indirme yapma, DB değeri istenen formatta değilse düzelt
        $newVal = ltrim($relPath, '/');
        if (file_exists($targetAbs)) {
            if ($val !== $newVal) {
                $rowsIndex[$id]['changes'][$col] = $newVal;
                $rowsIndex[$id]['msgs'][] = $col . ' DB düzeltildi (dosya mevcut)';
            } else {
                $rowsIndex[$id]['msgs'][] = $col . ' zaten doğru';
            }
            // Akışlı bilgi
            stream_echo('<div>id#' . htmlspecialchars((string)$id) . ' ' . htmlspecialchars($name) . ': ' . htmlspecialchars(end($rowsIndex[$id]['msgs'])) . '</div>');
            continue;
        }
        // Dosya yoksa indirme görevi ekle
        $tasks[] = [ 'id'=>$id, 'name'=>$name, 'col'=>$col, 'url'=>$val, 'relPath'=>$relPath, 'targetAbs'=>$targetAbs ];
    }
}

// Eşzamanlı indirme: curl_multi
$cc = isset($_GET['cc']) ? max(1, min(12, (int)$_GET['cc'])) : 6;
$mh = curl_multi_init();
$handles = [];
$openFiles = [];

$addTask = function($task) use (&$mh, &$handles, &$openFiles, $dry) {
    $ch = curl_init($task['url']);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => !$dry,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_CONNECTTIMEOUT => 8,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_USERAGENT => 'BlackbetAdmin/1.0',
    ]);
    if (defined('CURL_HTTP_VERSION_2_0')) { @curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); }
    if (!$dry) {
        $dir = dirname($task['targetAbs']); if (!is_dir($dir)) { @mkdir($dir, 0777, true); }
        $fp = @fopen($task['targetAbs'], 'wb'); if ($fp) { $openFiles[(int)$ch] = $fp; curl_setopt($ch, CURLOPT_FILE, $fp); }
    }
    $handles[(int)$ch] = $task;
    curl_multi_add_handle($mh, $ch);
};

$i = 0; $n = count($tasks);
while ($i < $n && count($handles) < $cc) { $addTask($tasks[$i++]); }

do {
    $status = curl_multi_exec($mh, $running);
    if ($status > CURLM_OK) break;
    while ($info = curl_multi_info_read($mh)) {
        $ch = $info['handle']; $task = $handles[(int)$ch];
        $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); $err = curl_error($ch);
        if (isset($openFiles[(int)$ch])) { fclose($openFiles[(int)$ch]); unset($openFiles[(int)$ch]); }
        curl_multi_remove_handle($mh, $ch); curl_close($ch); unset($handles[(int)$ch]);
        if ($info['result'] === CURLE_OK && $http < 400) {
            if (!$dry) { $downloaded++; }
            $rowsIndex[$task['id']]['msgs'][] = $task['col'] . ' indirildi';
            $newVal = ltrim($task['relPath'], '/');
            $rowsIndex[$task['id']]['changes'][$task['col']] = $newVal;
        } else {
            $errors[] = 'id#' . $task['id'] . ' ' . $task['col'] . ' indirilemedi: HTTP ' . $http . ' ' . $err;
            $rowsIndex[$task['id']]['msgs'][] = $task['col'] . ' hata (indirilemedi)';
        }
        if ($i < $n) { $addTask($tasks[$i++]); }
        stream_echo('<div>id#' . htmlspecialchars((string)$task['id']) . ' ' . htmlspecialchars($task['name']) . ': ' . htmlspecialchars(end($rowsIndex[$task['id']]['msgs'])) . '</div>');
    }
    usleep(10000);
} while ($running || !empty($handles));

curl_multi_close($mh);

// DB güncellemeleri ve akışlı özet
foreach ($rowsIndex as $id => $info) {
    if (!empty($info['changes'])) {
        $processed++;
        $logs[] = ['id' => $id, 'name' => $info['name'], 'changes' => $info['changes']];
        if (!$dry) {
            $setParts = []; $params = [':id' => $id];
            foreach ($info['changes'] as $k => $v) { $setParts[] = "$k = :$k"; $params[":$k"] = $v; }
            $sql = 'UPDATE games SET ' . implode(', ', $setParts) . ' WHERE id = :id';
            $up = $pdo->prepare($sql);
            if ($up->execute($params)) { $updated++; $rowsIndex[$id]['msgs'][] = 'DB güncellendi'; }
            else { $errors[] = "id#$id DB güncellenemedi"; $rowsIndex[$id]['msgs'][] = 'DB güncellenemedi'; }
        }
        stream_echo('<div>id#' . htmlspecialchars((string)$id) . ' ' . htmlspecialchars($info['name']) . ': ' . htmlspecialchars(implode(', ', $info['msgs'])) . '</div>');
    } else {
        $skipped++;
        stream_echo('<div>id#' . htmlspecialchars((string)$id) . ' ' . htmlspecialchars($info['name']) . ': değişiklik yok</div>');
    }
}

stream_echo('<hr><h3>Görsel Aynalama Özeti</h3>');
echo '<ul>';
echo '<li>İşlenen kayıt: <strong>' . htmlspecialchars((string)$processed) . '</strong></li>';
echo '<li>İndirilen dosya: <strong>' . htmlspecialchars((string)$downloaded) . '</strong></li>';
echo '<li>Güncellenen kayıt: <strong>' . htmlspecialchars((string)$updated) . '</strong></li>';
echo '<li>Atlanan: <strong>' . htmlspecialchars((string)$skipped) . '</strong></li>';
echo '<li>Kip: <strong>' . ($dry ? 'Dry-run' : 'Gerçek') . '</strong></li>';
echo '</ul>';

if ($logs) {
    echo '<hr><h4>Değişiklikler</h4><div class="table-responsive">';
    echo '<table class="table table-sm table-striped"><thead><tr><th>ID</th><th>Oyun</th><th>Alan</th><th>Yeni Değer</th></tr></thead><tbody>';
    foreach ($logs as $log) {
        foreach ($log['changes'] as $field => $val) {
            echo '<tr>';
            echo '<td>' . htmlspecialchars((string)$log['id']) . '</td>';
            echo '<td>' . htmlspecialchars($log['name'] ?? '') . '</td>';
            echo '<td>' . htmlspecialchars($field) . '</td>';
            echo '<td><code>' . htmlspecialchars($val) . '</code></td>';
            echo '</tr>';
        }
    }
    echo '</tbody></table></div>';
}

if ($errors) {
    echo '<hr><h4>Hatalar</h4><ul>';
    foreach ($errors as $e) echo '<li>' . htmlspecialchars($e) . '</li>';
    echo '</ul>';
}

stream_echo('<hr><p>İşlem tamamlandı.</p>');