<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
header('Content-Type: application/json');
require_once __DIR__ . '/db.php';

$json = file_get_contents('php://input');
$data = json_decode($json, true);

if (!is_array($data) || empty($data['vm_id'])) {
    echo json_encode(['status' => 'error', 'msg' => 'vm_id missing']);
    exit;
}

$vmId        = (int)$data['vm_id'];
$isHeartbeat = (isset($data['action']) && $data['action'] === 'heartbeat');
$ip          = $conn->real_escape_string(trim($data['ip_address']    ?? $_SERVER['REMOTE_ADDR'] ?? ''));
$token       = $conn->real_escape_string(trim($data['earnapp_token'] ?? ''));
$group       = $conn->real_escape_string(trim($data['group_name']    ?? ''));
$rdp         = $conn->real_escape_string(trim($data['rdp_nickname']  ?? ''));

$agentVer = $conn->real_escape_string(trim($data['agent_version'] ?? ''));

$statRaw = trim($data['status'] ?? '');
$allowed = ['Running', 'Blocked', 'Paused', 'Connecting', 'Offline', 'Online'];
$stat    = in_array($statRaw, $allowed, true) ? $statRaw : '';
if ($stat === 'Connecting') $stat = 'Offline';
$statSafe = $conn->real_escape_string($stat);

$bal  = null;
if (isset($data['balance']) && $data['balance'] !== '') {
    $bal = (float)preg_replace('/[^0-9.]/', '', (string)$data['balance']);
}
$traf = (float)preg_replace('/[^0-9.]/', '', (string)($data['traffic'] ?? '0'));

$row = $conn->query("SELECT id, status FROM vms WHERE id = $vmId LIMIT 1");
if (!$row || $row->num_rows === 0) {
    echo json_encode(['status' => 'error', 'msg' => 'VM not registered']);
    exit;
}
$vm              = $row->fetch_assoc();
$currentDbStatus = $vm['status'] ?? '';

if ($token !== '') {
    $dup = $conn->query("SELECT id FROM vms WHERE earnapp_token = '$token' AND id != $vmId LIMIT 1");
    if ($dup && $dup->num_rows > 0) {
        $oldRow = $dup->fetch_assoc();
        $conn->query("UPDATE vms SET earnapp_token = NULL, status = 'Offline' WHERE id = " . (int)$oldRow['id']);
    }
}

$sets = [];
$sets[] = "current_ip = '$ip'";
$sets[] = "last_heartbeat = NOW()";

$shouldUpdateStatus = false;
if ($stat === 'Online' && in_array($currentDbStatus, ['Offline', '', null], true)) {
    $shouldUpdateStatus = true;
} elseif ($stat !== '' && $stat !== 'Online') {
    $shouldUpdateStatus = true;
}
if ($shouldUpdateStatus) {
    $sets[] = "status = '$statSafe'";
}

if (!$isHeartbeat) {
    $sets[] = "traffic = $traf";
    if ($token !== '') {
        $sets[] = "earnapp_token = '$token'";
    }
    if ($bal !== null) {
        $sets[] = "balance = $bal";
    }
}

if ($agentVer !== '') {
    $curVerRow = $conn->query("SELECT agent_version, unit_id, rdp_nickname, group_name FROM vms WHERE id = $vmId LIMIT 1");
    $curVerData = $curVerRow ? $curVerRow->fetch_assoc() : null;
    $oldVer = $curVerData['agent_version'] ?? null;
    $sets[] = "agent_version = '$agentVer'";

    if ($curVerData && $oldVer !== $agentVer) {
        $unitIdLog = $conn->real_escape_string($curVerData['unit_id'] ?? '');
        $rdpLog    = $conn->real_escape_string($curVerData['rdp_nickname'] ?? '');
        $grpLog    = $conn->real_escape_string($curVerData['group_name'] ?? '');
        $oldVerLog = $conn->real_escape_string($oldVer ?? '');
        $event     = ($oldVer === null || $oldVer === '') ? 'first_seen' : (version_compare($agentVer, $oldVer, '<') ? 'downgrade' : 'update');
        $conn->query("INSERT INTO agent_update_log (vm_id, unit_id, rdp_nickname, group_name, old_version, new_version, ip_address, event) VALUES ($vmId, '$unitIdLog', '$rdpLog', '$grpLog', '$oldVerLog', '$agentVer', '$ip', '$event')");

        $pendingPush = $conn->query("SELECT s.id, p.to_version FROM agent_push_vm_status s JOIN agent_push_log p ON p.id=s.push_id WHERE s.vm_id=$vmId AND s.status='pending' ORDER BY s.id DESC LIMIT 1");
        if ($pendingPush && $pendingPush->num_rows > 0) {
            $ps = $pendingPush->fetch_assoc();
            $newStatus = ($agentVer === $ps['to_version']) ? 'done' : 'failed';
            $failReason = ($newStatus === 'failed') ? $conn->real_escape_string("Got v$agentVer, expected v{$ps['to_version']}") : '';
            $conn->query("UPDATE agent_push_vm_status SET status='$newStatus', fail_reason='$failReason', updated_at=NOW() WHERE id=" . (int)$ps['id']);
            $pushId2 = $conn->query("SELECT push_id FROM agent_push_vm_status WHERE id=" . (int)$ps['id'] . " LIMIT 1");
            if ($pushId2) {
                $pid = (int)$pushId2->fetch_assoc()['push_id'];
                $conn->query("UPDATE agent_push_log SET done_vms=(SELECT COUNT(*) FROM agent_push_vm_status WHERE push_id=$pid AND status='done'), failed_vms=(SELECT COUNT(*) FROM agent_push_vm_status WHERE push_id=$pid AND status='failed') WHERE id=$pid");
            }
        }
    }
}

$sql = "UPDATE vms SET " . implode(', ', $sets) . " WHERE id = $vmId";
if (!$conn->query($sql)) {
    echo json_encode(['status' => 'error', 'msg' => 'Update failed: ' . $conn->error]);
    exit;
}

if (!$isHeartbeat && $token !== '' && in_array($stat, ['Running', 'Blocked', 'Paused'], true)) {
    $balHist = ($bal !== null) ? (float)$bal : 0.0;
    $conn->query("INSERT INTO earnapp_history (vm_id, earnapp_token, ip_address, redeem_balance, cashout_detected, status, earning_date, recorded_at) VALUES ($vmId, '$token', '$ip', $balHist, 0, '$statSafe', CURDATE(), NOW())");
}

echo json_encode(['status' => 'success']);
?>