<?php
declare(strict_types=1);
/**
 * RBC AI Agent — deterministic action endpoint.
 *
 * Accepts: POST JSON { action, params, csrf_token, confirm? }
 * Returns: JSON { success, action, summary, result }
 *
 * No LLM is involved in deciding *what* to run. The dashboard's action modals
 * already hold exact values in <select> elements; previously they stringified
 * those into an English sentence and posted it to the streaming endpoint, where
 * a model re-parsed it back into parameters. That round trip is where "JHS 2"
 * became "JH3" and every downstream query silently matched zero rows.
 *
 * Individual actions may still call the AI internally (to write a remark, or an
 * executive summary) — that is fine. What is removed is the guesswork about
 * which action to run and with what arguments.
 */

if (session_status() === PHP_SESSION_NONE) session_start();
set_time_limit(300);

require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../ai/agent_guard.php';
require_once __DIR__ . '/../ai/class_resolver.php';
require_once __DIR__ . '/../ai/agent_brain.php';
require_once __DIR__ . '/../ai/provider_engine.php';

// Action handlers
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';
require_once __DIR__ . '/../ai/actions/bulk_create_canteen_entitlements.php';
require_once __DIR__ . '/../ai/actions/canteen_daily_report.php';
require_once __DIR__ . '/../ai/actions/cancel_canteen_session.php';
require_once __DIR__ . '/../ai/actions/send_canteen_reminder_sms.php';

header('Content-Type: application/json');

$input = json_decode((string) file_get_contents('php://input'), true) ?? [];

// ── Auth: login + role + module licence + CSRF ────────────────────────────
$user_id = rbcRequireAgentAccess('json', true, (string) ($input['csrf_token'] ?? ''));

$action  = trim((string) ($input['action'] ?? ''));
$params  = is_array($input['params'] ?? null) ? $input['params'] : [];
$confirm = !empty($input['confirm']);

$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',
    'bulk_create_canteen_entitlements' => 'action_bulk_create_canteen_entitlements',
    'canteen_daily_report'             => 'action_canteen_daily_report',
    'cancel_canteen_session'           => 'action_cancel_canteen_session',
    'send_canteen_reminder_sms'        => 'action_send_canteen_reminder_sms',
];

$fn = $action_map[$action] ?? null;
if ($fn === null || !function_exists($fn)) {
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'error'   => $action === '' ? 'No action given.' : "Unknown action: {$action}",
        'valid_actions' => array_keys($action_map),
    ]);
    exit;
}

// ── Resolve the class name before the action queries on it ────────────────
$conn = getDBConnection();
$res  = rbcResolveClassParam($params, $conn instanceof mysqli ? $conn : null);
if (!$res['ok']) {
    http_response_code(422);
    echo json_encode([
        'success'       => false,
        'action'        => $action,
        'error'         => $res['error'],
        'valid_classes' => $res['valid_classes'] ?? [],
    ]);
    exit;
}
$params = $res['params'];

// ── Confirmation gate for anything that spends money or contacts parents ──
$warning = rbcActionNeedsConfirmation($action, $params);
if ($warning !== null && !$confirm) {
    echo json_encode([
        'success'              => false,
        'action'               => $action,
        'needs_confirmation'   => true,
        'confirmation_message' => $warning,
        'params'               => $params,
    ]);
    exit;
}

// ── Record the task, run it, record the outcome ───────────────────────────
$task_id = null;
if ($conn instanceof mysqli) {
    if ($stmt = $conn->prepare(
        "INSERT INTO ai_tasks (task_type, payload, status, triggered_by, created_by, started_at, created_at)
         VALUES (?,?,'running','manual',?,NOW(),NOW())"
    )) {
        $payload = json_encode($params);
        $stmt->bind_param('ssi', $action, $payload, $user_id);
        $stmt->execute();
        $task_id = (int) $conn->insert_id;
        $stmt->close();
    }
}

$started = microtime(true);
try {
    $result = $fn($params);
} catch (Throwable $e) {
    error_log("ai_action [{$action}] threw: " . $e->getMessage());
    $result = ['success' => false, 'error' => 'The action failed: ' . $e->getMessage()];
}
$elapsed_ms = (int) round((microtime(true) - $started) * 1000);

// Always close the task row — the old chat path left rows stuck in 'running'
// whenever an action threw.
if ($task_id !== null && $conn instanceof mysqli) {
    $status  = !empty($result['success']) ? 'completed' : 'failed';
    $res_json = json_encode($result);
    if ($upd = $conn->prepare(
        "UPDATE ai_tasks SET status = ?, result = ?, completed_at = NOW() WHERE id = ?"
    )) {
        $upd->bind_param('ssi', $status, $res_json, $task_id);
        $upd->execute();
        $upd->close();
    }
}

echo json_encode([
    'success'     => (bool) ($result['success'] ?? false),
    'action'      => $action,
    'summary'     => AgentBrain::formatResult($action, is_array($result) ? $result : []),
    'result'      => $result,
    'task_id'     => $task_id,
    'elapsed_ms'  => $elapsed_ms,
    'resolved_class' => $params['class_name'] ?? null,
], JSON_UNESCAPED_UNICODE);
