<?php
/**
 * Cron Job Script: Auto-Complete Confirmed Appointments
 * 
 * This script automatically completes confirmed appointments whose time has passed.
 * It should be run every few minutes via cron job.
 * 
 * Usage: php complete_confirmed_appointments.php
 * Cron: Run every 5 minutes using crontab
 * Add to crontab: 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/bin/php /path/to/astro_admin/admin/complete_confirmed_appointments.php
 */

// Set timezone
date_default_timezone_set('Asia/Kolkata');

// Include database configuration
require_once '../config/database.php';

// Log file path
$logFile = '../logs/cron_complete_appointments.log';

// Create logs directory if it doesn't exist
$logDir = dirname($logFile);
if (!is_dir($logDir)) {
    mkdir($logDir, 0755, true);
}

/**
 * Log function to write messages to log file
 */
function writeLog($message) {
    global $logFile;
    $timestamp = date('Y-m-d H:i:s');
    $logMessage = "[$timestamp] $message" . PHP_EOL;
    file_put_contents($logFile, $logMessage, FILE_APPEND | LOCK_EX);
}

/**
 * Parse time slot string to get end time
 * Format: "09:00 AM - 10:00 AM" or "10:00 AM - 11:00 AM" or "09:00-10:00"
 * Returns: DateTime object for end time or false on failure
 */
function parseTimeSlotEndTime($timeSlot, $appointmentDate) {
    try {
        // Remove extra spaces
        $timeSlot = trim($timeSlot);
        
        // Try different patterns to extract end time
        
        // Pattern 1: "09:00 AM - 10:00 AM" or "09:00 AM-10:00 AM"
        if (preg_match('/-\s*(\d{1,2}:\d{2}\s*(?:AM|PM|am|pm))/i', $timeSlot, $matches)) {
            $endTimeStr = trim($matches[1]);
            
            // Combine date and time
            $dateStr = $appointmentDate . ' ' . $endTimeStr;
            
            // Try format: Y-m-d g:i A (9:00 AM) or Y-m-d h:i A (09:00 AM)
            $endTime = DateTime::createFromFormat('Y-m-d g:i A', $dateStr);
            if ($endTime === false) {
                $endTime = DateTime::createFromFormat('Y-m-d h:i A', $dateStr);
            }
            
            if ($endTime !== false) {
                return $endTime;
            }
        }
        
        // Pattern 2: "09:00-10:00" (24 hour format without AM/PM)
        if (preg_match('/-\s*(\d{1,2}:\d{2})/', $timeSlot, $matches)) {
            $endTimeStr = trim($matches[1]);
            
            // Combine date and time
            $dateStr = $appointmentDate . ' ' . $endTimeStr;
            
            // Try 24 hour format
            $endTime = DateTime::createFromFormat('Y-m-d H:i', $dateStr);
            if ($endTime === false) {
                $endTime = DateTime::createFromFormat('Y-m-d G:i', $dateStr);
            }
            
            if ($endTime !== false) {
                return $endTime;
            }
        }
        
        // Pattern 3: Single time like "10:00 AM" - treat as end time
        if (preg_match('/^(\d{1,2}:\d{2}\s*(?:AM|PM|am|pm))$/i', $timeSlot, $matches)) {
            $endTimeStr = trim($matches[1]);
            $dateStr = $appointmentDate . ' ' . $endTimeStr;
            
            $endTime = DateTime::createFromFormat('Y-m-d g:i A', $dateStr);
            if ($endTime === false) {
                $endTime = DateTime::createFromFormat('Y-m-d h:i A', $dateStr);
            }
            
            if ($endTime !== false) {
                return $endTime;
            }
        }
        
        // If all patterns fail, log the actual format
        writeLog("WARNING: Could not parse time slot format: '$timeSlot' for date: $appointmentDate");
        return false;
        
    } catch (Exception $e) {
        writeLog("ERROR parsing time slot '$timeSlot': " . $e->getMessage());
        return false;
    }
}

/**
 * Main function to complete confirmed appointments whose time has passed
 */
function completeConfirmedAppointments() {
    try {
        // Get database connection
        $pdo = getDBConnection();
        
        $currentTime = new DateTime();
        writeLog("Starting completion process. Current time: " . $currentTime->format('Y-m-d H:i:s'));
        
        // Find confirmed appointments that have date and time set
        $query = "
            SELECT id, user_name, user_mobile, appointment_date, time_slot, status, created_at
            FROM appointments 
            WHERE status = 'confirmed' 
            AND appointment_date IS NOT NULL 
            AND appointment_date != '' 
            AND time_slot IS NOT NULL 
            AND time_slot != ''
            ORDER BY appointment_date ASC, time_slot ASC
        ";
        
        $stmt = $pdo->query($query);
        $confirmedAppointments = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        $completedCount = 0;
        $errorCount = 0;
        $skippedCount = 0;
        
        if (empty($confirmedAppointments)) {
            writeLog("No confirmed appointments found to process");
            return [
                'completed' => 0,
                'errors' => 0,
                'skipped' => 0,
                'total_found' => 0
            ];
        }
        
        writeLog("Found " . count($confirmedAppointments) . " confirmed appointments to check");
        
        // Process each appointment
        foreach ($confirmedAppointments as $appointment) {
            try {
                $appointmentDate = $appointment['appointment_date'];
                $timeSlot = $appointment['time_slot'];
                
                // Parse end time from time slot
                $endTime = parseTimeSlotEndTime($timeSlot, $appointmentDate);
                
                if ($endTime === false) {
                    // If time slot parsing fails, check if appointment date itself is in the past
                    $appointmentDateTime = DateTime::createFromFormat('Y-m-d', $appointmentDate);
                    if ($appointmentDateTime !== false) {
                        // Set to end of day (23:59:59) for comparison
                        $appointmentDateTime->setTime(23, 59, 59);
                        
                        if ($appointmentDateTime < $currentTime) {
                            // Appointment date has passed, complete it
                            $updateQuery = "
                                UPDATE appointments 
                                SET status = 'completed', 
                                    updated_at = NOW()
                                WHERE id = ? AND status = 'confirmed'
                            ";
                            
                            $updateStmt = $pdo->prepare($updateQuery);
                            $result = $updateStmt->execute([$appointment['id']]);
                            
                            if ($result && $updateStmt->rowCount() > 0) {
                                $completedCount++;
                                writeLog("COMPLETED (date-based): Appointment ID: {$appointment['id']} for {$appointment['user_name']} - Date: $appointmentDate (time slot parse failed: '$timeSlot')");
                            } else {
                                $skippedCount++;
                                writeLog("SKIPPED: Appointment ID: {$appointment['id']} - Status may have changed");
                            }
                        } else {
                            $skippedCount++;
                            writeLog("SKIPPED: Could not parse time slot for appointment ID: {$appointment['id']} - Time slot: '$timeSlot', Date: $appointmentDate (date is in future)");
                        }
                    } else {
                        $skippedCount++;
                        writeLog("SKIPPED: Could not parse time slot or date for appointment ID: {$appointment['id']} - Time slot: '$timeSlot', Date: $appointmentDate");
                    }
                    continue;
                }
                
                // Check if end time has passed
                if ($endTime < $currentTime) {
                    // Update status to completed
                    $updateQuery = "
                        UPDATE appointments 
                        SET status = 'completed', 
                            updated_at = NOW()
                        WHERE id = ? AND status = 'confirmed'
                    ";
                    
                    $updateStmt = $pdo->prepare($updateQuery);
                    $result = $updateStmt->execute([$appointment['id']]);
                    
                    if ($result && $updateStmt->rowCount() > 0) {
                        $completedCount++;
                        $endTimeStr = $endTime->format('Y-m-d H:i:s');
                        writeLog("COMPLETED: Appointment ID: {$appointment['id']} for {$appointment['user_name']} ({$appointment['user_mobile']}) - Date: $appointmentDate, Time: $timeSlot, End Time: $endTimeStr");
                    } else {
                        // Appointment might have been updated by someone else
                        $skippedCount++;
                        writeLog("SKIPPED: Appointment ID: {$appointment['id']} - Status may have changed");
                    }
                    
                } else {
                    // Time hasn't passed yet
                    $endTimeStr = $endTime->format('Y-m-d H:i:s');
                    $currentTimeStr = $currentTime->format('Y-m-d H:i:s');
                    writeLog("PENDING: Appointment ID: {$appointment['id']} - Time hasn't passed yet. End time: $endTimeStr, Current time: $currentTimeStr");
                }
                
            } catch (Exception $e) {
                $errorCount++;
                writeLog("ERROR: Exception while processing appointment ID {$appointment['id']}: " . $e->getMessage());
            }
        }
        
        // Log summary
        writeLog("Completion process finished. Completed: $completedCount, Skipped: $skippedCount, Errors: $errorCount");
        
        // Return summary
        return [
            'completed' => $completedCount,
            'errors' => $errorCount,
            'skipped' => $skippedCount,
            'total_found' => count($confirmedAppointments)
        ];
        
    } catch (Exception $e) {
        writeLog("CRITICAL ERROR: " . $e->getMessage());
        throw $e;
    }
}

/**
 * Get statistics about confirmed appointments
 */
function getConfirmedStats() {
    try {
        $pdo = getDBConnection();
        $currentTime = new DateTime();
        
        // Get total confirmed appointments
        $stmt = $pdo->query("SELECT COUNT(*) as count FROM appointments WHERE status = 'confirmed' AND appointment_date IS NOT NULL AND appointment_date != '' AND time_slot IS NOT NULL AND time_slot != ''");
        $totalConfirmed = $stmt->fetch(PDO::FETCH_ASSOC)['count'];
        
        // Get confirmed appointments whose time has passed
        $stmt = $pdo->query("
            SELECT id, appointment_date, time_slot 
            FROM appointments 
            WHERE status = 'confirmed' 
            AND appointment_date IS NOT NULL 
            AND appointment_date != '' 
            AND time_slot IS NOT NULL 
            AND time_slot != ''
        ");
        $appointments = $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        $overdueCount = 0;
        foreach ($appointments as $appointment) {
            $endTime = parseTimeSlotEndTime($appointment['time_slot'], $appointment['appointment_date']);
            if ($endTime !== false && $endTime < $currentTime) {
                $overdueCount++;
            }
        }
        
        return [
            'total_confirmed' => $totalConfirmed,
            'overdue' => $overdueCount
        ];
    } catch (Exception $e) {
        writeLog("ERROR getting stats: " . $e->getMessage());
        return [
            'total_confirmed' => 0,
            'overdue' => 0
        ];
    }
}

// Main execution
if (php_sapi_name() === 'cli' || isset($_GET['run_cron'])) {
    try {
        writeLog("=== CRON JOB STARTED ===");
        
        // Get stats before processing
        $statsBefore = getConfirmedStats();
        if ($statsBefore) {
            writeLog("Stats before: Total confirmed: {$statsBefore['total_confirmed']}, Overdue: {$statsBefore['overdue']}");
        }
        
        // Run the completion process
        $result = completeConfirmedAppointments();
        
        // Get stats after processing
        $statsAfter = getConfirmedStats();
        if ($statsAfter) {
            writeLog("Stats after: Total confirmed: {$statsAfter['total_confirmed']}, Overdue: {$statsAfter['overdue']}");
        }
        
        writeLog("=== CRON JOB COMPLETED ===");
        if ($result) {
            writeLog("Summary: Completed {$result['completed']} appointments, Skipped: {$result['skipped']}, Errors: {$result['errors']}");
        } else {
            writeLog("Summary: No confirmed appointments found to complete");
            $result = ['completed' => 0, 'errors' => 0, 'skipped' => 0, 'total_found' => 0];
        }
        
        // Output for web interface
        if (isset($_GET['run_cron'])) {
            header('Content-Type: application/json');
            echo json_encode([
                'success' => true,
                'message' => 'Cron job executed successfully',
                'completed' => $result['completed'],
                'skipped' => $result['skipped'],
                'errors' => $result['errors'],
                'total_found' => $result['total_found'],
                'stats_before' => $statsBefore,
                'stats_after' => $statsAfter
            ]);
        }
        
    } catch (Exception $e) {
        writeLog("FATAL ERROR: " . $e->getMessage());
        if (isset($_GET['run_cron'])) {
            header('Content-Type: application/json');
            http_response_code(500);
            echo json_encode([
                'success' => false,
                'message' => 'Cron job failed: ' . $e->getMessage()
            ]);
        }
    }
} elseif (isset($_GET['get_stats'])) {
    // Return statistics only
    header('Content-Type: application/json');
    try {
        $stats = getConfirmedStats();
        echo json_encode([
            'success' => true,
            'stats' => $stats
        ]);
    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode([
            'success' => false,
            'message' => 'Error getting stats: ' . $e->getMessage()
        ]);
    }
} else {
    // Auto-run cron job when page loads, but allow manual execution too
    $autoRun = !isset($_GET['manual']) && !isset($_GET['get_stats']);
    $cronResult = null;
    $statsData = null;
    
    if ($autoRun) {
        // Automatically run the cron job
        try {
            writeLog("=== AUTO-RUN CRON JOB STARTED ===");
            
            // Get stats before processing
            $statsBefore = getConfirmedStats();
            
            // Run the completion process
            $cronResult = completeConfirmedAppointments();
            
            // Get stats after processing
            $statsAfter = getConfirmedStats();
            
            writeLog("=== AUTO-RUN CRON JOB COMPLETED ===");
            
            $statsData = [
                'before' => $statsBefore,
                'after' => $statsAfter
            ];
        } catch (Exception $e) {
            writeLog("FATAL ERROR in auto-run: " . $e->getMessage());
            $cronResult = [
                'success' => false,
                'message' => 'Cron job failed: ' . $e->getMessage(),
                'completed' => 0,
                'skipped' => 0,
                'errors' => 1,
                'total_found' => 0
            ];
        }
    } else {
        // Get stats only if requested
        $statsData = ['current' => getConfirmedStats()];
    }
    
    // Web interface
    ?>
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Complete Confirmed Appointments - Cron Job</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
        <style>
            body { background: #f8f9fa; padding: 20px; }
            .card { margin-bottom: 20px; }
            .auto-run-notice { animation: fadeIn 0.5s; }
            @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="card">
                <div class="card-header bg-success text-white">
                    <h4><i class="fas fa-check-circle me-2"></i>Complete Confirmed Appointments Cron Job</h4>
                </div>
                <div class="card-body">
                    <p>This cron job automatically completes confirmed appointments whose appointment time has passed.</p>
                    
                    <?php if ($autoRun && $cronResult): ?>
                        <div class="alert alert-info auto-run-notice">
                            <i class="fas fa-info-circle me-2"></i><strong>Auto-executed:</strong> Cron job ran automatically when page loaded.
                        </div>
                    <?php endif; ?>
                    
                    <div class="d-grid gap-2 d-md-flex">
                        <button class="btn btn-primary" onclick="runCronJob()">
                            <i class="fas fa-play me-2"></i>Run Cron Job Now
                        </button>
                        <button class="btn btn-info" onclick="getStats()">
                            <i class="fas fa-chart-bar me-2"></i>Get Statistics
                        </button>
                        <a href="?" class="btn btn-secondary">
                            <i class="fas fa-redo me-2"></i>Refresh (Auto-Run)
                        </a>
                    </div>
                    
                    <div id="result" class="mt-3">
                        <?php if ($autoRun && $cronResult): ?>
                            <?php if (isset($cronResult['success']) && $cronResult['success'] === false): ?>
                                <div class="alert alert-danger">
                                    <h6><i class="fas fa-exclamation-triangle me-2"></i>Cron Job Failed</h6>
                                    <p class="mb-0"><?php echo htmlspecialchars($cronResult['message'] ?? 'Unknown error'); ?></p>
                                </div>
                            <?php else: ?>
                                <div class="alert alert-success">
                                    <h6><i class="fas fa-check-circle me-2"></i>Cron Job Completed Successfully</h6>
                                    <p class="mb-0">
                                        <strong>Completed:</strong> <?php echo $cronResult['completed'] ?? 0; ?> appointments<br>
                                        <strong>Skipped:</strong> <?php echo $cronResult['skipped'] ?? 0; ?> appointments<br>
                                        <strong>Errors:</strong> <?php echo $cronResult['errors'] ?? 0; ?><br>
                                        <strong>Total found:</strong> <?php echo $cronResult['total_found'] ?? 0; ?>
                                    </p>
                                    <?php if ($statsData && isset($statsData['before']) && isset($statsData['after'])): ?>
                                        <hr>
                                        <p class="mb-0">
                                            <strong>Stats Before:</strong> Total confirmed: <?php echo $statsData['before']['total_confirmed'] ?? 0; ?>, Overdue: <?php echo $statsData['before']['overdue'] ?? 0; ?><br>
                                            <strong>Stats After:</strong> Total confirmed: <?php echo $statsData['after']['total_confirmed'] ?? 0; ?>, Overdue: <?php echo $statsData['after']['overdue'] ?? 0; ?>
                                        </p>
                                    <?php endif; ?>
                                </div>
                            <?php endif; ?>
                        <?php endif; ?>
                        
                        <?php if (!$autoRun && $statsData && isset($statsData['current'])): ?>
                            <div class="alert alert-info">
                                <h6><i class="fas fa-chart-bar me-2"></i>Statistics</h6>
                                <p class="mb-0">
                                    Total Confirmed Appointments: <?php echo $statsData['current']['total_confirmed'] ?? 0; ?><br>
                                    Overdue Appointments (time passed): <?php echo $statsData['current']['overdue'] ?? 0; ?>
                                </p>
                            </div>
                        <?php endif; ?>
                    </div>
                </div>
            </div>
        </div>
        
        <script>
            function runCronJob() {
                const resultDiv = document.getElementById('result');
                resultDiv.innerHTML = '<div class="alert alert-info"><i class="fas fa-spinner fa-spin me-2"></i>Running cron job...</div>';
                
                fetch('?run_cron=1')
                    .then(response => response.json())
                    .then(data => {
                        if (data.success) {
                            resultDiv.innerHTML = `
                                <div class="alert alert-success">
                                    <h6><i class="fas fa-check-circle me-2"></i>Cron Job Completed Successfully</h6>
                                    <p class="mb-0">
                                        Completed: ${data.completed} appointments<br>
                                        Skipped: ${data.skipped} appointments<br>
                                        Errors: ${data.errors}<br>
                                        Total found: ${data.total_found}
                                    </p>
                                    ${data.stats_after ? `
                                        <hr>
                                        <p class="mb-0">
                                            <strong>Stats After:</strong> Total confirmed: ${data.stats_after.total_confirmed}, Overdue: ${data.stats_after.overdue}
                                        </p>
                                    ` : ''}
                                </div>
                            `;
                        } else {
                            resultDiv.innerHTML = `
                                <div class="alert alert-danger">
                                    <h6><i class="fas fa-exclamation-triangle me-2"></i>Cron Job Failed</h6>
                                    <p class="mb-0">${data.message}</p>
                                </div>
                            `;
                        }
                    })
                    .catch(error => {
                        resultDiv.innerHTML = `
                            <div class="alert alert-danger">
                                <h6><i class="fas fa-exclamation-triangle me-2"></i>Error</h6>
                                <p class="mb-0">Failed to run cron job: ${error.message}</p>
                            </div>
                        `;
                    });
            }
            
            function getStats() {
                const resultDiv = document.getElementById('result');
                resultDiv.innerHTML = '<div class="alert alert-info"><i class="fas fa-spinner fa-spin me-2"></i>Loading statistics...</div>';
                
                fetch('?get_stats=1')
                    .then(response => response.json())
                    .then(data => {
                        if (data.success) {
                            resultDiv.innerHTML = `
                                <div class="alert alert-info">
                                    <h6><i class="fas fa-chart-bar me-2"></i>Statistics</h6>
                                    <p class="mb-0">
                                        Total Confirmed Appointments: ${data.stats.total_confirmed}<br>
                                        Overdue Appointments (time passed): ${data.stats.overdue}
                                    </p>
                                </div>
                            `;
                        }
                    })
                    .catch(error => {
                        resultDiv.innerHTML = `
                            <div class="alert alert-danger">
                                <h6><i class="fas fa-exclamation-triangle me-2"></i>Error</h6>
                                <p class="mb-0">Failed to get statistics: ${error.message}</p>
                            </div>
                        `;
                    });
            }
        </script>
        
        <script>
    // ====== Option A: Auto-run on page load with a cooldown (recommended) ======
    // This will call runCronJob() automatically when the page loads,
    // but only if it hasn't run in the last X minutes from this browser.
    (function() {
        const COOLDOWN_MINUTES = 5; // cooldown between automatic runs (minutes)
        const storageKey = 'cron_last_run_timestamp';

        document.addEventListener('DOMContentLoaded', function () {
            try {
                const lastRun = parseInt(localStorage.getItem(storageKey) || '0', 10);
                const now = Date.now();

                if (!lastRun || (now - lastRun) > COOLDOWN_MINUTES * 60 * 1000) {
                    // Mark attempted run time first to reduce duplicate clicks on very fast reloads
                    localStorage.setItem(storageKey, String(now));
                    runCronJob();
                } else {
                    // Optional: show message or do nothing
                    console.log('Auto-run skipped due to cooldown. Last run:', new Date(lastRun).toLocaleString());
                }
            } catch (e) {
                console.error('Error checking cron cooldown', e);
                // fallback: still try to run
                runCronJob();
            }
        });
    })();


    // ====== Option B: Immediately "click" the Run button on load (simple) ======
    // This literally triggers a click on the Run button. Use only if server does NOT already auto-run.
    /*
    document.addEventListener('DOMContentLoaded', function () {
        const runBtn = document.querySelector('.btn.btn-primary');
        if (runBtn) runBtn.click();
    });
    */


    // ====== Option C: Remove server-side auto-run and instead let client hit ?run_cron=1 ======
    // If you prefer the client to be the only trigger remove/disable the PHP auto-run block
    // and use runCronJob() on load (Option A/B) — avoids double execution.
    //
    // Note: If you keep PHP auto-run AND also auto-trigger client run, it may run twice.
</script>

    </body>
    </html>
    <?php
}
?>

