<?php
file_put_contents(__DIR__ . '/test_alive.txt', time());

ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(0);

ini_set("log_errors", 1);
ini_set("error_log", __DIR__ . "/php-error.log");

require_once("../config/session.php");
require_once("../config/config.php");
require_once("../config/function.php");

header('Content-Type: application/json; charset=utf-8');

function respond($success, $message) {
    echo json_encode([
        "success" => $success,
        "message" => $message
    ]);
    exit;
}

function safeRelativePath($path) {
    $docRoot = realpath($_SERVER['DOCUMENT_ROOT']);
    $real = str_replace('\\', '/', $path);

    if ($docRoot) {
        $docRoot = str_replace('\\', '/', $docRoot);
        $real = str_replace($docRoot, 'public_html', $real);
    }

    return $real;
}

function downloadFile($url, $path) {
    $ch = curl_init($url);

    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_TIMEOUT => 120,
        CURLOPT_CONNECTTIMEOUT => 30,
        CURLOPT_USERAGENT => 'Mozilla/5.0'
    ]);

    $data = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if (curl_errno($ch)) {
        $err = curl_error($ch);
        curl_close($ch);
        respond(false, "❌ cURL Error: " . $err);
    }

    curl_close($ch);

    if ($httpCode < 200 || $httpCode >= 300 || empty($data)) {
        respond(false, "❌ Download failed. HTTP Code: " . $httpCode);
    }

    if (@file_put_contents($path, $data) === false) {
        respond(false, "❌ Cannot save update.zip. Folder permission issue.");
    }

    return true;
}

if (!isset($_SESSION["is_login"], $_SESSION["login_token"]) || $_SESSION["is_login"] !== true || empty($_SESSION["login_token"])) {
    session_unset();
    session_destroy();
    redirect("../members/logout", 0);
    exit;
}

$user_data = user_data($_SESSION["login_token"]);

if (empty($user_data['user_id']) || $user_data['login_token'] !== $_SESSION["login_token"]) {
    session_unset();
    session_destroy();
    redirect("../members/logout", 0);
    exit;
}

if ($user_data['user_id'] != '1' || $user_data['usertype'] != 'Admin') {
    respond(false, "❌ Unauthorized Access.");
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    respond(false, "❌ Invalid request method.");
}

$input = json_decode(file_get_contents("php://input"), true);

if (
    !$input ||
    empty($input['update_url']) ||
    empty($input['version']) ||
    !isset($input['extractPath'])
) {
    respond(false, "❌ Invalid request received.");
}

$updateUrl = trim($input['update_url']);
$newVersion = trim($input['version']);

$baseDir = realpath(__DIR__);
$extractRaw = trim($input['extractPath']);

$extractPath = realpath($baseDir . '/' . $extractRaw);

if (!$extractPath) {
    $extractPath = $baseDir . '/' . trim($extractRaw, '/');
    if (!is_dir($extractPath)) {
        if (!@mkdir($extractPath, 0755, true)) {
            respond(false, "❌ Failed to create directory: " . safeRelativePath($extractPath));
        }
    }
    $extractPath = realpath($extractPath);
}

if (!$extractPath || !is_dir($extractPath)) {
    respond(false, "❌ Invalid extraction path.");
}

if (!is_writable($extractPath)) {
    @chmod($extractPath, 0755);
}

if (!is_writable($extractPath)) {
    respond(false, "❌ Extraction folder is not writable: " . safeRelativePath($extractPath));
}

$zipFile = __DIR__ . '/update.zip';

downloadFile($updateUrl, $zipFile);

$zip = new ZipArchive;

if ($zip->open($zipFile) !== true) {
    @unlink($zipFile);
    respond(false, "❌ Failed to open ZIP file. The file may be corrupted.");
}

for ($i = 0; $i < $zip->numFiles; $i++) {
    $entry = $zip->getNameIndex($i);

    $entry = str_replace('\\', '/', $entry);
    $entry = ltrim($entry, '/');

    if ($entry === '' || strpos($entry, '../') !== false || strpos($entry, '..\\') !== false) {
        continue;
    }

    $fullPath = $extractPath . '/' . $entry;

    if (substr($entry, -1) === '/') {
        if (!is_dir($fullPath)) {
            @mkdir($fullPath, 0755, true);
        }
        continue;
    }

    $dirPath = dirname($fullPath);

    if (!is_dir($dirPath)) {
        if (!@mkdir($dirPath, 0755, true)) {
            $zip->close();
            @unlink($zipFile);
            respond(false, "❌ Cannot create folder: " . safeRelativePath($dirPath));
        }
    }

    @chmod($dirPath, 0755);

    if (!is_writable($dirPath)) {
        $zip->close();
        @unlink($zipFile);
        respond(false, "❌ Folder permission denied: " . safeRelativePath($dirPath));
    }

    if (file_exists($fullPath)) {
        @chmod($fullPath, 0644);

        if (!is_writable($fullPath)) {
            $zip->close();
            @unlink($zipFile);
            respond(false, "❌ File permission denied: " . safeRelativePath($fullPath) . " | Set file permission 644 and owner same cPanel user.");
        }
    }

    $stream = $zip->getStream($entry);

    if (!$stream) {
        continue;
    }

    $fp = @fopen($fullPath, 'wb');

    if (!$fp) {
        fclose($stream);
        $zip->close();
        @unlink($zipFile);
        respond(false, "❌ Extraction Failed: Permission denied in " . safeRelativePath($fullPath));
    }

    while (!feof($stream)) {
        fwrite($fp, fread($stream, 8192));
    }

    fclose($fp);
    fclose($stream);

    @chmod($fullPath, 0644);
}

$zip->close();
@unlink($zipFile);

$sqlFile = $extractPath . '/update.sql';

if (!file_exists($sqlFile)) {
    respond(false, "❌ update.sql not found in extracted files.");
}

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

try {
    $conn = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
    $conn->set_charset("utf8mb4");
} catch (Exception $e) {
    respond(false, "❌ Database connection failed: " . $e->getMessage());
}

$sqlQueries = file_get_contents($sqlFile);
$queries = explode(";", $sqlQueries);

foreach ($queries as $query) {
    $query = trim($query);

    if ($query !== '') {
        try {
            $conn->query($query);
        } catch (mysqli_sql_exception $e) {
            $errorMessage = $e->getMessage();

            if (
                stripos($errorMessage, 'Duplicate column name') !== false ||
                stripos($errorMessage, 'Duplicate key name') !== false ||
                stripos($errorMessage, 'already exists') !== false
            ) {
                continue;
            }

            $conn->close();
            respond(false, "❌ SQL Error: " . $errorMessage . " | Query: " . $query);
        }
    }
}

@unlink($sqlFile);
$conn->close();

@file_put_contents(__DIR__ . '/current_version.txt', $newVersion);

respond(true, "✅ Update applied successfully and database updated!");