<?php
/**
 * RBC AI Cron Runner
 * Called by a server cron job to execute scheduled AI tasks.
 *
 * Cron example (daily at 6am):
 *   0 6 * * * php /path/to/edutrack/ai_cron.php >> /var/log/edutrack_ai_cron.log 2>&1
 *
 * Security: Only accessible from CLI or whitelisted IPs.
 */

declare(strict_types=1);

// Allow CLI or local IP only
if (php_sapi_name() !== 'cli') {
    $allowed = ['127.0.0.1', '::1'];
    if (!in_array($_SERVER['REMOTE_ADDR'] ?? '', $allowed, true)) {
        http_response_code(403);
        exit('Forbidden');
    }
}

require_once __DIR__ . '/config.php';
require_once __DIR__ . '/ai/provider_engine.php';
require_once __DIR__ . '/ai/actions/send_fee_reminders.php';
require_once __DIR__ . '/ai/actions/generate_terminal_reports.php';
require_once __DIR__ . '/ai/actions/generate_exam_paper.php';
require_once __DIR__ . '/ai/actions/detect_at_risk_students.php';
require_once __DIR__ . '/ai/actions/financial_snapshot.php';
require_once __DIR__ . '/ai/actions/send_weekly_feeding_summary.php';
require_once __DIR__ . '/ai/actions/check_timetable_conflicts.php';
require_once __DIR__ . '/ai/actions/bulk_notify_parents.php';
require_once __DIR__ . '/ai/actions/batch_generate_report_pdfs.php';
require_once __DIR__ . '/ai/actions/create_parent_accounts_bulk.php';

$action_map = [
    'send_fee_reminders'          => 'action_send_fee_reminders',
    'generate_terminal_reports'   => 'action_generate_terminal_reports',
    'generate_exam_paper'         => 'action_generate_exam_paper',
    'detect_at_risk_students'     => 'action_detect_at_risk_students',
    'financial_snapshot'          => 'action_financial_snapshot',
    'send_weekly_feeding_summary' => 'action_send_weekly_feeding_summary',
    'check_timetable_conflicts'   => 'action_check_timetable_conflicts',
    'bulk_notify_parents'         => 'action_bulk_notify_parents',
    'batch_generate_report_pdfs'  => 'action_batch_generate_report_pdfs',
    'create_parent_accounts_bulk' => 'action_create_parent_accounts_bulk',
];

$conn = getDBConnection();
if (!$conn) {
    echo "ERROR: Could not connect to database.\n";
    exit(1);
}

$now = date('Y-m-d H:i:s');
echo "RBC AI Cron started at {$now}\n";

// Get due schedules
$stmt = $conn->prepare(
    "SELECT * FROM ai_schedules
     WHERE is_active = 1
     AND (next_run IS NULL OR next_run <= ?)
     ORDER BY next_run ASC"
);
$stmt->bind_param('s', $now);
$stmt->execute();
$schedules = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);

echo count($schedules) . " schedule(s) due.\n";

foreach ($schedules as $schedule) {
    $task_type = $schedule['task_type'];
    $payload   = json_decode($schedule['payload'] ?? '{}', true) ?: [];
    $sched_id  = (int) $schedule['id'];

    echo "  Processing: {$task_type} (schedule #{$sched_id})\n";

    // Create task record
    $ins_stmt = $conn->prepare(
        "INSERT INTO ai_tasks
         (task_type, payload, status, triggered_by, started_at, created_at)
         VALUES (?, ?, 'running', 'scheduled', NOW(), NOW())"
    );
    $payload_json = json_encode($payload);
    $ins_stmt->bind_param('ss', $task_type, $payload_json);
    $ins_stmt->execute();
    $task_id = (int) $conn->insert_id;

    $action_result = ['success' => false, 'error' => 'Unknown action'];
    $provider_used = null;

    $action_fn = $action_map[$task_type] ?? null;
    if ($action_fn && function_exists($action_fn)) {
        try {
            $action_result = $action_fn($payload);
            $provider_used = $action_result['provider_used'] ?? null;
        } catch (Throwable $e) {
            $action_result = ['success' => false, 'error' => $e->getMessage()];
            error_log("RBC Cron error [{$task_type}]: " . $e->getMessage());
        }
    } else {
        $action_result = ['success' => false, 'error' => "Action function not found: {$task_type}"];
    }

    // Update task record
    $result_json = json_encode($action_result);
    $status      = $action_result['success'] ? 'completed' : 'failed';
    $upd_stmt    = $conn->prepare(
        "UPDATE ai_tasks SET status=?, result=?, provider_used=?, completed_at=NOW() WHERE id=?"
    );
    $upd_stmt->bind_param('sssi', $status, $result_json, $provider_used, $task_id);
    $upd_stmt->execute();

    // Calculate next_run based on schedule pattern
    $next_run = calculateNextRun($schedule);

    // Update schedule last_run and next_run
    $upd_sched = $conn->prepare(
        "UPDATE ai_schedules SET last_run=NOW(), next_run=? WHERE id=?"
    );
    $upd_sched->bind_param('si', $next_run, $sched_id);
    $upd_sched->execute();

    $status_display = $action_result['success'] ? 'OK' : 'FAILED';
    echo "  [{$status_display}] {$task_type} — next run: {$next_run}\n";
}

echo "RBC AI Cron complete. " . count($schedules) . " task(s) processed.\n";

/**
 * Calculate the next run date/time based on schedule configuration.
 */
function calculateNextRun(array $schedule): string
{
    $run_time   = $schedule['run_time'] ?? '08:00:00';
    $day_of_week = strtolower($schedule['day_of_week'] ?? 'daily');

    // Ensure run_time has seconds
    if (strlen($run_time) === 5) {
        $run_time .= ':00';
    }

    if ($day_of_week === 'daily') {
        return date('Y-m-d', strtotime('+1 day')) . ' ' . $run_time;
    }

    $days_map = [
        'monday' => 'Monday', 'tuesday' => 'Tuesday', 'wednesday' => 'Wednesday',
        'thursday' => 'Thursday', 'friday' => 'Friday', 'saturday' => 'Saturday', 'sunday' => 'Sunday',
    ];

    if (isset($days_map[$day_of_week])) {
        return date('Y-m-d', strtotime('next ' . $days_map[$day_of_week])) . ' ' . $run_time;
    }

    // Default: tomorrow
    return date('Y-m-d', strtotime('+1 day')) . ' ' . $run_time;
}
