<?php
// ====== CONFIG ======
error_reporting(E_ALL);
ini_set('display_errors', 1);
date_default_timezone_set('Asia/Kolkata');

require_once '../config/database.php'; // getDBConnection() expected

$LOG_FILE        = __DIR__ . '/../logs/cron_cancel_bookings.log';
$LOCK_FILE       = sys_get_temp_dir() . '/cancel_pending_bookings.lock';
$REQUIRE_TOKEN   = false;              // <- agar token chahiye to true kar dein
$WEB_TOKEN       = 'SOME_LONG_RANDOM_SECRET'; // token value (agar $REQUIRE_TOKEN = true)

// ====== Ensure logs dir ======
$logDir = dirname($LOG_FILE);
if (!is_dir($logDir)) {
    mkdir($logDir, 0755, true);
}

// ====== Helpers ======
function writeLog($message) {
    global $LOG_FILE;
    $timestamp = date('Y-m-d H:i:s');
    $logMessage = "[$timestamp] $message" . PHP_EOL;
    file_put_contents($LOG_FILE, $logMessage, FILE_APPEND | LOCK_EX);
}

function withLockOrExit() {
    global $LOCK_FILE;
    static $fp = null;

    $fp = fopen($LOCK_FILE, 'c');
    if ($fp === false) {
        writeLog('ERROR: Unable to open lock file.');
        return false;
    }
    if (!flock($fp, LOCK_EX | LOCK_NB)) {
        writeLog('Another instance is running. Exiting.');
        return false;
    }
    // keep handle open till script ends
    register_shutdown_function(function() use ($fp) {
        if ($fp) {
            flock($fp, LOCK_UN);
            fclose($fp);
        }
    });
    return true;
}

// ====== Core ======
function cancelPendingBookings() {
    try {
        $pdo = getDBConnection();

        // 10 minutes ago
        $tenMinutesAgo = date('Y-m-d H:i:s', strtotime('-10 minutes'));
        writeLog("Starting cancellation process for bookings older than: $tenMinutesAgo");

        // Fetch pending older than 10 mins
        $q = "
            SELECT id, user_name, user_mobile, appointment_date, time_slot, created_at
            FROM appointments
            WHERE status = 'pending' AND created_at < ?
            ORDER BY created_at ASC
        ";
        $stmt = $pdo->prepare($q);
        $stmt->execute([$tenMinutesAgo]);
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $cancelled = 0; $errors = 0;
        if (!$rows) {
            writeLog("No pending appointments found to cancel");
            return ['cancelled'=>0,'errors'=>0,'total_found'=>0];
        }

        writeLog("Found ".count($rows)." pending appointments to cancel");

        // Prepare update once
        $noteAppend = "\n[Auto-cancelled] Cancelled automatically due to pending status for more than 10 minutes on ".date('Y-m-d H:i:s');
        $uq = "
            UPDATE appointments
            SET status = 'cancelled',
                updated_at = NOW(),
                notes = CONCAT(IFNULL(notes, ''), ?)
            WHERE id = ? AND status = 'pending'
        ";
        $up = $pdo->prepare($uq);

        foreach ($rows as $r) {
            try {
                $ok = $up->execute([$noteAppend, $r['id']]);
                if ($ok && $up->rowCount() > 0) {
                    $cancelled++;
                    writeLog("Cancelled appointment ID: {$r['id']} for {$r['user_name']} ({$r['user_mobile']}) - Booked: {$r['created_at']}");
                } else {
                    $errors++;
                    writeLog("ERROR: Failed/Skipped cancel for ID: {$r['id']} (maybe status changed)");
                }
            } catch (Exception $e) {
                $errors++;
                writeLog("ERROR: Exception while cancelling ID {$r['id']}: ".$e->getMessage());
            }
        }

        writeLog("Cancellation process completed. Cancelled: $cancelled, Errors: $errors");
        return ['cancelled'=>$cancelled,'errors'=>$errors,'total_found'=>count($rows)];

    } catch (Exception $e) {
        writeLog("CRITICAL ERROR: ".$e->getMessage());
        throw $e;
    }
}

function getPendingStats() {
    try {
        $pdo = getDBConnection();
        $q = "
            SELECT 
                COUNT(*) as total_pending,
                SUM(CASE WHEN created_at < DATE_SUB(NOW(), INTERVAL 10 MINUTE) THEN 1 ELSE 0 END) as old_pending
            FROM appointments 
            WHERE status = 'pending'
        ";
        $stmt = $pdo->prepare($q);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC);
    } catch (Exception $e) {
        writeLog("ERROR getting stats: " . $e->getMessage());
        return ['total_pending'=>0,'old_pending'=>0];
    }
}

// ====== Routing ======
// JSON endpoints for programmatic use (kept for compatibility)
if (isset($_GET['run_cron'])) {
    header('Content-Type: application/json');
    if (!withLockOrExit()) {
        echo json_encode(['success'=>true,'message'=>'Another instance is running; exiting gracefully','cancelled'=>0,'errors'=>0,'total_found'=>0]);
        exit;
    }
    try {
        $res = cancelPendingBookings();
        echo json_encode(['success'=>true,'message'=>'Cron job completed','cancelled'=>$res['cancelled'],'errors'=>$res['errors'],'total_found'=>$res['total_found']]);
    } catch (Exception $e) {
        echo json_encode(['success'=>false,'message'=>'Cron job failed: '.$e->getMessage()]);
    }
    exit;
}

if (isset($_GET['get_stats'])) {
    header('Content-Type: application/json');
    $stats = getPendingStats();
    echo json_encode(['success'=>true,'stats'=>$stats]);
    exit;
}

// ====== AUTO-RUN on page load (web) OR on CLI ======
$isCLI = (php_sapi_name() === 'cli');
if ($isCLI) {
    if (!withLockOrExit()) {
        // another instance running; exit non-error
        echo "Another instance is running. Exiting.\n";
        exit(0);
    }
    try {
        writeLog("=== CRON JOB STARTED (CLI) ===");
        $r = cancelPendingBookings();
        writeLog("=== CRON JOB COMPLETED (CLI) ===");
        echo "Cancelled: {$r['cancelled']}, Errors: {$r['errors']}\n";
        exit(0);
    } catch (Exception $e) {
        writeLog("CRITICAL ERROR in cron job: ".$e->getMessage());
        echo "Error: ".$e->getMessage()."\n";
        exit(1);
    }
} else {
    // Web request: optional token check
    if ($REQUIRE_TOKEN) {
        if (!isset($_GET['token']) || $_GET['token'] !== $WEB_TOKEN) {
            http_response_code(403);
            echo "<h3 style='font-family:Arial'>Forbidden</h3>";
            exit;
        }
    }

    // Auto-run on page load
    $ran = false;
    $runResult = ['cancelled'=>0,'errors'=>0,'total_found'=>0];
    if (withLockOrExit()) {
        try {
            writeLog("=== CRON JOB STARTED (WEB AUTO) ===");
            $runResult = cancelPendingBookings();
            writeLog("=== CRON JOB COMPLETED (WEB AUTO) ===");
            $ran = true;
        } catch (Exception $e) {
            writeLog("CRITICAL ERROR in web auto-run: ".$e->getMessage());
        }
    }
    $stats = getPendingStats();
}
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Cron Auto – Cancel Pending Bookings</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; background: #f5f5f5; }
        .container { max-width: 800px; margin: 0 auto; background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
        .alert { padding: 15px; margin: 10px 0; border-radius: 6px; border: 1px solid transparent; }
        .success { background:#d4edda; color:#155724; border-color:#c3e6cb; }
        .danger { background:#f8d7da; color:#721c24; border-color:#f5c6cb; }
        .info { background:#d1ecf1; color:#0c5460; border-color:#bee5eb; }
        .stats { display:flex; gap:20px; margin:20px 0; }
        .stat { flex:1; text-align:center; background:#f8f9fa; padding:16px; border-radius:8px; }
        .num { font-size:2rem; font-weight:bold; color:#007bff; }
        code { background:#f1f3f5; padding:2px 6px; border-radius:4px; }
        .muted { color:#666; font-size: 0.95rem; }
    </style>
</head>
<body>
<div class="container">
    <h2>🕐 Cancel Pending Bookings — Auto Run</h2>

    <?php if (isset($ran) && $ran): ?>
        <div class="alert success">
            <strong>Auto-run completed.</strong><br>
            Cancelled: <b><?=htmlspecialchars((string)$runResult['cancelled'])?></b> |
            Errors: <b><?=htmlspecialchars((string)$runResult['errors'])?></b> |
            Total found: <b><?=htmlspecialchars((string)$runResult['total_found'])?></b>
        </div>
    <?php else: ?>
        <div class="alert info">
            <strong>Auto-run skipped</strong> (another instance is already running or lock unavailable).
        </div>
    <?php endif; ?>

    <div class="stats">
        <div class="stat">
            <div class="num"><?=htmlspecialchars((string)($stats['total_pending'] ?? 0))?></div>
            <div>Total Pending</div>
        </div>
        <div class="stat">
            <div class="num"><?=htmlspecialchars((string)($stats['old_pending'] ?? 0))?></div>
            <div>Old Pending (&gt; 10 min)</div>
        </div>
    </div>

    <div class="alert info">
        <div><strong>How to set Cron (cPanel):</strong></div>
        <div class="muted">cPanel → <em>Cron Jobs</em> → Add New Cron Job</div>
        <div>Every 5 minutes:</div>
        <code>/usr/bin/php <?=htmlspecialchars(__FILE__)?></code>
    </div>

    <div class="muted">
        Log file: <code><?=htmlspecialchars($LOG_FILE)?></code>
    </div>
</div>
</body>
</html>
