<?php
/**
 * Integrity Check Cron Job
 * 
 * Run every 6 hours to verify license integrity:
 *   1. Recalculate integrity checksum from license.dat + system.lock + bind_hash
 *   2. Compare with DB stored value
 *   3. If mismatch → set locked=1 in DB → system locked
 *   4. Also re-validates against remote API
 * 
 * Cron example:
 *   0 */6 * * * wget --spider -O - https://yourdomain.com/automations/cronjobs/integrity_check.php
 */
ini_set('max_execution_time', '120');
define("BASEPATH", TRUE);

require $_SERVER["DOCUMENT_ROOT"] . "/vendor/autoload.php";
require $_SERVER["DOCUMENT_ROOT"] . "/app/init.php";

// Load core components
require_once $_SERVER["DOCUMENT_ROOT"] . "/core/cipher.php";
require_once $_SERVER["DOCUMENT_ROOT"] . "/core/sentinel.php";
require_once $_SERVER["DOCUMENT_ROOT"] . "/core/shield.php";

$root = $_SERVER["DOCUMENT_ROOT"];
$licenseDatPath  = $root . '/config/license.dat';
$systemLockPath  = $root . '/config/system.lock';
$logPath         = $root . '/storage/logs/integrity_cron.log';

function _ic_log($path, $msg) {
    $dir = dirname($path);
    if (!is_dir($dir)) @mkdir($dir, 0755, true);
    @file_put_contents($path, '[' . date('Y-m-d H:i:s') . '] ' . $msg . "\n", FILE_APPEND | LOCK_EX);
}

// ─── 1. Check critical files exist ─────────────────────────────────
if (!_shield_check_files()) {
    _ic_log($logPath, 'ALERT: Critical files missing — locking system');
    try {
        $conn->exec("UPDATE system_integrity SET locked=1, lock_reason='Critical files missing or tampered' WHERE id=1");
    } catch (Exception $e) {}
    echo "INTEGRITY CHECK FAILED: Files missing\n";
    exit(1);
}

// ─── 2. Decrypt license and get binding hash ───────────────────────
$license = _cipher_read_license($licenseDatPath);
if ($license === false || empty($license['bind_hash'])) {
    _ic_log($logPath, 'ALERT: Cannot decrypt license.dat — locking system');
    try {
        $conn->exec("UPDATE system_integrity SET locked=1, lock_reason='License file decryption failed' WHERE id=1");
    } catch (Exception $e) {}
    echo "INTEGRITY CHECK FAILED: Decryption error\n";
    exit(1);
}

// ─── 3. Verify binding hash against current environment ────────────
$domain = _sentinel_current_domain();
$ip = _sentinel_current_ip();

if (!_sentinel_verify($license['bind_hash'], $domain, $ip, $license['license_key'])) {
    _ic_log($logPath, "ALERT: Bind hash mismatch — domain=$domain ip=$ip — locking system");
    try {
        $conn->exec("UPDATE system_integrity SET locked=1, lock_reason='Binding hash mismatch (domain or IP changed)' WHERE id=1");
    } catch (Exception $e) {}
    echo "INTEGRITY CHECK FAILED: Binding mismatch\n";
    exit(1);
}

// ─── 4. Recalculate integrity checksum and compare with DB ─────────
$currentChecksum = _sentinel_integrity_checksum($licenseDatPath, $systemLockPath, $license['bind_hash']);

try {
    $stmt = $conn->prepare("SELECT integrity_checksum, locked FROM system_integrity WHERE id=1");
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    
    if (!$row) {
        _ic_log($logPath, 'ALERT: No integrity row in DB — locking system');
        echo "INTEGRITY CHECK FAILED: No DB record\n";
        exit(1);
    }
    
    if ((int)$row['locked'] === 1) {
        _ic_log($logPath, 'NOTICE: System already locked');
        echo "SYSTEM ALREADY LOCKED\n";
        exit(1);
    }
    
    if (!hash_equals($row['integrity_checksum'], $currentChecksum)) {
        _ic_log($logPath, "ALERT: Integrity checksum mismatch — DB tampered — locking system");
        $conn->exec("UPDATE system_integrity SET locked=1, lock_reason='Integrity checksum mismatch' WHERE id=1");
        echo "INTEGRITY CHECK FAILED: Checksum mismatch\n";
        exit(1);
    }
} catch (Exception $e) {
    _ic_log($logPath, 'WARNING: DB check failed — ' . $e->getMessage());
}

// ─── 5. Remote API re-validation ───────────────────────────────────
if (!empty($license['api_url']) && function_exists('curl_init')) {
    $postData = [
        'license_key'  => $license['license_key'],
        'domain'       => $domain,
        'ip'           => $ip,
        'product_slug' => $license['product_slug'] ?? '',
    ];
    
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $license['api_url'],
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => http_build_query($postData),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_HTTPHEADER     => ['User-Agent: SMMPanel-Cron/2.0', 'Accept: application/json'],
    ]);
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    if ($response !== false) {
        $apiData = @json_decode($response, true);
        if (is_array($apiData) && isset($apiData['status']) && $apiData['status'] !== 'valid') {
            _ic_log($logPath, "ALERT: API rejected license — status=" . $apiData['status'] . " — locking system");
            try {
                $conn->exec("UPDATE system_integrity SET locked=1, lock_reason='License server rejected: " . addslashes($apiData['status']) . "' WHERE id=1");
            } catch (Exception $e) {}
            echo "INTEGRITY CHECK FAILED: API rejection\n";
            exit(1);
        }
    }
}

// ─── 6. All good — update timestamp ────────────────────────────────
try {
    $stmt = $conn->prepare("UPDATE system_integrity SET last_validated_at = :now, integrity_checksum = :cs WHERE id = 1");
    $stmt->execute([
        'now' => date('Y-m-d H:i:s'),
        'cs'  => $currentChecksum,
    ]);
} catch (Exception $e) {
    _ic_log($logPath, 'WARNING: Could not update validation timestamp — ' . $e->getMessage());
}

// Update file cache too
$cacheDir = $root . '/storage';
if (!is_dir($cacheDir)) @mkdir($cacheDir, 0755, true);
$cacheData = [
    'status'     => 'valid',
    'timestamp'  => time(),
    'domain'     => $domain,
    'checked_at' => date('Y-m-d H:i:s'),
];
@file_put_contents($cacheDir . '/license_check_cache.json', json_encode($cacheData, JSON_PRETTY_PRINT), LOCK_EX);

_ic_log($logPath, "OK: All integrity checks passed (domain=$domain)");
echo "INTEGRITY CHECK PASSED\n";
