<?php

/**
 * Progress Analytics — data endpoint (admin app).
 *
 * Thin dispatcher: authenticate, gate on the module, resolve the access
 * context, normalise the scope, and hand off to progress_query.php. All numbers
 * come from the query library so every surface agrees.
 *
 * Actions (?action=):
 *   filters    filter-bar options (years, terms, classes, subjects)
 *   dashboard  everything for one scope in a single round-trip:
 *              kpis, trend, subjects, distribution, table (+ student header)
 *
 * Scope params: level, academic_year, term, classes (csv), student_id,
 *               subjects (csv), sex, pass_mark.
 */

require_once dirname(__DIR__, 2) . '/config.php';
require_once dirname(__DIR__) . '/lib/progress_query.php';
require_once dirname(__DIR__) . '/lib/progress_access.php';

if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

header('Content-Type: application/json; charset=utf-8');

// Authentication FIRST. requireModule() only checks role-access + license, and
// an unauthenticated session falls through to the default 'tutor' role — which
// is whitelisted for this module — so without this explicit check a logged-out
// caller would reach the dispatcher. (The access context would still scope them
// to no classes, but the endpoint must reject them outright, not rely on that.)
if (empty($_SESSION['user_id'])) {
    http_response_code(401);
    echo json_encode(['success' => false, 'message' => 'Please sign in.']);
    exit;
}

// Module gate (also enforces ROLE_ACCESS; 403 JSON on failure).
requireModule('progress_analytics', true);

$conn = getDBConnection();
if (!$conn instanceof mysqli) {
    http_response_code(500);
    echo json_encode(['success' => false, 'message' => 'Database unavailable.']);
    exit;
}

$action  = $_GET['action'] ?? 'dashboard';
$context = progressAccessContext();

try {
    switch ($action) {
        case 'filters':
            echo json_encode([
                'success' => true,
                'filters' => progressFilterOptions($conn, $context['allowed_classes']),
                'access'  => [
                    'restricted'      => $context['allowed_classes'] !== null,
                    'allowed_classes' => $context['allowed_classes'],
                ],
            ]);
            break;

        case 'students':
            // Students in a class, for the Student-view picker. Class is
            // validated against the caller's allowed set so a scoped user
            // cannot enumerate students outside their classes.
            $class = trim((string) ($_GET['class'] ?? ''));
            $allowed = $context['allowed_classes'];
            if ($class === '' || ($allowed !== null && !in_array($class, $allowed, true))) {
                echo json_encode(['success' => true, 'students' => []]);
                break;
            }
            $stmt = $conn->prepare(
                "SELECT id, student_id AS admission_no, first_name, last_name
                   FROM students
                  WHERE class = ? AND status = 'active'
                  ORDER BY first_name, last_name"
            );
            $stmt->bind_param('s', $class);
            $stmt->execute();
            $res = $stmt->get_result();
            $students = [];
            while ($row = $res->fetch_assoc()) {
                $students[] = [
                    'id'    => (int) $row['id'],
                    'label' => trim($row['first_name'] . ' ' . $row['last_name']) . ' (' . $row['admission_no'] . ')',
                ];
            }
            $stmt->close();
            echo json_encode(['success' => true, 'students' => $students]);
            break;

        case 'dashboard':
            $scope = progressBuildScope($_GET, $context);

            $payload = [
                'success'      => true,
                'scope'        => $scope,
                'kpis'         => progressKpis($conn, $scope),
                'trend'        => progressTrend($conn, $scope),
                'subjects'     => progressSubjectBreakdown($conn, $scope),
                'distribution' => progressGradeDistribution($conn, $scope),
                'table'        => progressTableRows($conn, $scope),
            ];

            if ($scope['level'] === 'student' && $scope['student_id'] > 0) {
                $payload['student'] = progressStudentHeader($conn, $scope['student_id']);
            }

            // Deeper panels only make sense for school/class scopes — a single
            // student has no heatmap, cohort movement or class-wide scatter.
            if ($scope['level'] !== 'student') {
                $payload['heatmap']    = progressHeatmap($conn, $scope);
                $payload['movement']   = progressRankMovement($conn, $scope);
                $payload['attendance'] = progressAttendanceScatter($conn, $scope);
            }

            echo json_encode($payload);
            break;

        case 'insight':
            // Premium AI narrative. Requires an AI module on top of the
            // analytics addon; returns a locked flag (not an error) otherwise so
            // the UI can hide the feature cleanly.
            require_once dirname(__DIR__) . '/lib/progress_insight.php';
            if (!progressInsightAvailable()) {
                echo json_encode(['success' => false, 'locked' => true,
                    'message' => 'AI summaries require a premium AI module.']);
                break;
            }
            $scope = progressBuildScope($_GET, $context);
            $out = progressInsightGenerate($conn, $scope);
            echo json_encode([
                'success'   => $out['success'],
                'narrative' => $out['narrative'],
                'provider'  => $out['provider'],
                'message'   => $out['error'] ?? '',
            ]);
            break;

        case 'compare':
            // Two scopes side by side. compare_by = 'class' (b_class vs the
            // primary class) or 'term' (b_term vs the primary term).
            $scopeA = progressBuildScope($_GET, $context);
            $compareBy = ($_GET['compare_by'] ?? 'class') === 'term' ? 'term' : 'class';

            $bInput = $_GET;
            if ($compareBy === 'class') {
                $bInput['classes'] = $_GET['b_class'] ?? '';
            } else {
                $bInput['term'] = $_GET['b_term'] ?? '';
            }
            $scopeB = progressBuildScope($bInput, $context);

            $labelA = $compareBy === 'class'
                ? (implode(', ', $scopeA['classes']) ?: 'All classes')
                : ($scopeA['term'] ?: 'All terms');
            $labelB = $compareBy === 'class'
                ? (implode(', ', $scopeB['classes']) ?: 'All classes')
                : ($scopeB['term'] ?: 'All terms');

            $cmp = progressCompare($conn, $scopeA, $scopeB);
            echo json_encode([
                'success'    => true,
                'compare_by' => $compareBy,
                'a'          => array_merge($cmp['a'], ['label' => $labelA]),
                'b'          => array_merge($cmp['b'], ['label' => $labelB]),
            ]);
            break;

        default:
            http_response_code(400);
            echo json_encode(['success' => false, 'message' => 'Unknown action.']);
    }
} catch (Throwable $e) {
    error_log('progress-analytics data.php: ' . $e->getMessage());
    http_response_code(500);
    echo json_encode(['success' => false, 'message' => 'Failed to build analytics.']);
}
