<?php
/**
 * Teacher Portal — SBA (School-Based Assessment) component marks.
 *
 * GET  ?action=board&class=&subject=   -> component types + students + scores + CA preview
 * POST {action:'save_components', ...}  -> create/update/deactivate component types
 * POST {action:'save_scores', ...}      -> save per-component scores, recompute `scores`
 */
declare(strict_types=1);
require_once __DIR__ . '/tp_auth.php';
require_once dirname(__DIR__, 2) . '/lib/sba_engine.php';

$teacher_id = tp_require_auth();
$conn       = getDBConnection();
$ay         = (string) (getSettingValue('academic_year') ?? date('Y'));
$term       = (string) (getSettingValue('current_term')  ?? '');

/** Confirm the teacher may enter marks for this class-subject. */
function tp_sba_authorize(mysqli $conn, int $teacher_id, string $class_name, int $subject_id, string $ay): bool {
    $stmt = $conn->prepare(
        "SELECT 1 FROM class_subjects WHERE class_name = ? AND subject_id = ? AND teacher_id = ? LIMIT 1"
    );
    $stmt->bind_param('sii', $class_name, $subject_id, $teacher_id);
    $stmt->execute();
    $ok = $stmt->get_result()->num_rows > 0;
    $stmt->close();
    if ($ok) {
        return true;
    }

    $stmt = $conn->prepare(
        "SELECT 1 FROM timetable_slots
          WHERE class_name = ? AND subject_id = ? AND teacher_id = ? AND academic_year = ? LIMIT 1"
    );
    $stmt->bind_param('siis', $class_name, $subject_id, $teacher_id, $ay);
    $stmt->execute();
    $ok = $stmt->get_result()->num_rows > 0;
    $stmt->close();
    return $ok;
}

$method = $_SERVER['REQUEST_METHOD'];

// ── GET: assessment board ──────────────────────────────────────────────────
if ($method === 'GET' && ($_GET['action'] ?? '') === 'board') {
    $class_name = trim((string) ($_GET['class'] ?? ''));
    $subject_id = (int) ($_GET['subject'] ?? 0);

    if ($class_name === '' || $subject_id <= 0) {
        tp_json(false, null, 'Class and subject are required.');
    }
    if (!tp_sba_authorize($conn, $teacher_id, $class_name, $subject_id, $ay)) {
        tp_json(false, null, 'Subject not assigned to you for this class.');
    }

    $weighting  = sbaResolveWeighting($conn, $class_name, $subject_id);
    $components = sbaEnsureComponents($conn, $class_name, $subject_id, $term, $ay, $teacher_id);

    // Students with their component scores and a live CA preview.
    $stmt = $conn->prepare(
        "SELECT id, student_id, first_name, last_name, photo_path
           FROM students WHERE class = ? AND status = 'active'
          ORDER BY first_name, last_name"
    );
    $stmt->bind_param('s', $class_name);
    $stmt->execute();
    $students = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
    $stmt->close();

    foreach ($students as &$s) {
        $sid = (int) $s['id'];
        $s['photo_url'] = $s['photo_path']
            ? '../../' . ltrim($s['photo_path'], '/')
            : '../../assets/images/default-student.png';

        // Per-component scores.
        $scores = [];
        if (!empty($components)) {
            $ids = array_map(static fn($c) => (int) $c['id'], $components);
            $ph  = implode(',', array_fill(0, count($ids), '?'));
            $tps = str_repeat('i', count($ids) + 1);
            $q   = $conn->prepare("SELECT component_type_id, score FROM sba_scores WHERE student_id = ? AND component_type_id IN ($ph)");
            $q->bind_param($tps, ...array_merge([$sid], $ids));
            $q->execute();
            $rs = $q->get_result();
            while ($r = $rs->fetch_assoc()) {
                $scores[(int) $r['component_type_id']] = (float) $r['score'];
            }
            $q->close();
        }
        $s['scores'] = $scores;
        $s['ca_preview'] = sbaRolledUpClassScore($conn, $sid, $components, $weighting['max_class']);
    }
    unset($s);

    tp_json(true, [
        'class_name'    => $class_name,
        'subject_id'    => $subject_id,
        'term'          => $term,
        'academic_year' => $ay,
        'weighting'     => $weighting,
        'components'    => $components,
        'students'      => $students,
    ]);
}

// ── POST actions ────────────────────────────────────────────────────────────
if ($method === 'POST') {
    $input      = json_decode(file_get_contents('php://input'), true) ?? [];
    $action     = (string) ($input['action'] ?? '');
    $class_name = trim((string) ($input['class_name'] ?? ''));
    $subject_id = (int) ($input['subject_id'] ?? 0);

    if ($class_name === '' || $subject_id <= 0) {
        tp_json(false, null, 'Class and subject are required.');
    }
    if (!tp_sba_authorize($conn, $teacher_id, $class_name, $subject_id, $ay)) {
        tp_json(false, null, 'Not authorised to manage marks for this class/subject.');
    }

    // ── Save / update / deactivate component definitions ────────────────────
    if ($action === 'save_components') {
        $components = (array) ($input['components'] ?? []);
        if (empty($components)) {
            tp_json(false, null, 'Add at least one assessment component.');
        }

        $kept_ids = [];
        $order = 0;
        foreach ($components as $c) {
            $name = trim((string) ($c['component_name'] ?? ''));
            if ($name === '') {
                continue;
            }
            $max = max(1.0, (float) ($c['max_score'] ?? 100));
            $wt  = max(0.0, (float) ($c['weight'] ?? 1));
            $id  = (int) ($c['id'] ?? 0);

            if ($id > 0) {
                $u = $conn->prepare(
                    "UPDATE sba_component_types
                        SET component_name = ?, max_score = ?, weight = ?, display_order = ?, is_active = 1
                      WHERE id = ? AND class_name = ? AND subject_id = ? AND term = ? AND academic_year = ?"
                );
                $u->bind_param('sddiisiss', $name, $max, $wt, $order, $id, $class_name, $subject_id, $term, $ay);
                $u->execute();
                $u->close();
                $kept_ids[] = $id;
            } else {
                $i = $conn->prepare(
                    "INSERT INTO sba_component_types
                        (class_name, subject_id, teacher_id, component_name, max_score, weight, display_order, term, academic_year, is_active)
                     VALUES (?,?,?,?,?,?,?,?,?,1)"
                );
                $i->bind_param('siisddiss', $class_name, $subject_id, $teacher_id, $name, $max, $wt, $order, $term, $ay);
                $i->execute();
                $kept_ids[] = (int) $i->insert_id;
                $i->close();
            }
            $order++;
        }

        // Deactivate components the teacher removed (preserve their historical scores).
        $existing = sbaGetComponents($conn, $class_name, $subject_id, $term, $ay);
        foreach ($existing as $ec) {
            if (!in_array((int) $ec['id'], $kept_ids, true)) {
                $d = $conn->prepare("UPDATE sba_component_types SET is_active = 0 WHERE id = ?");
                $eid = (int) $ec['id'];
                $d->bind_param('i', $eid);
                $d->execute();
                $d->close();
            }
        }

        // Roll-up changed — recompute every active student's CA.
        sba_recalc_class($conn, $class_name, $subject_id, $term, $ay);

        tp_json(true, ['component_ids' => $kept_ids], 'Assessment components saved.');
    }

    // ── Save per-component scores ───────────────────────────────────────────
    if ($action === 'save_scores') {
        $records    = (array) ($input['records'] ?? []); // [{student_id, scores:{component_id:score}}]
        $components = sbaGetComponents($conn, $class_name, $subject_id, $term, $ay);
        $comp_max   = [];
        foreach ($components as $c) {
            $comp_max[(int) $c['id']] = (float) $c['max_score'];
        }

        $up = $conn->prepare(
            "INSERT INTO sba_scores (student_id, component_type_id, score, term, academic_year)
             VALUES (?,?,?,?,?)
             ON DUPLICATE KEY UPDATE score = VALUES(score), updated_at = NOW()"
        );

        $bounds = sbaLoadGradeBoundaries($conn, $class_name, $ay);
        $saved = 0;
        foreach ($records as $rec) {
            $sid = (int) ($rec['student_id'] ?? 0);
            if ($sid <= 0) {
                continue;
            }
            foreach ((array) ($rec['scores'] ?? []) as $cid => $val) {
                $cid = (int) $cid;
                if (!isset($comp_max[$cid])) {
                    continue; // ignore unknown / inactive components
                }
                $score = max(0.0, min((float) $val, $comp_max[$cid]));
                $up->bind_param('iidss', $sid, $cid, $score, $term, $ay);
                $up->execute();
            }
            // Recompute this student's combined score using the new CA roll-up.
            sbaRecalcAndPersistScore($conn, [
                'class_name'    => $class_name,
                'subject_id'    => $subject_id,
                'student_id'    => $sid,
                'term'          => $term,
                'academic_year' => $ay,
                'components'    => $components,
                'grade_bounds'  => $bounds,
            ]);
            $saved++;
        }
        $up->close();

        tp_json(true, ['saved' => $saved], "Assessment scores saved for {$saved} students.");
    }

    tp_json(false, null, 'Unknown action.');
}

tp_json(false, null, 'Invalid request.');

/** Recompute combined scores for every active student in a class-subject. */
function sba_recalc_class(mysqli $conn, string $class_name, int $subject_id, string $term, string $ay): void {
    $components = sbaGetComponents($conn, $class_name, $subject_id, $term, $ay);
    $bounds = sbaLoadGradeBoundaries($conn, $class_name, $ay);

    $stmt = $conn->prepare("SELECT id FROM students WHERE class = ? AND status = 'active'");
    $stmt->bind_param('s', $class_name);
    $stmt->execute();
    $rows = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
    $stmt->close();

    foreach ($rows as $r) {
        sbaRecalcAndPersistScore($conn, [
            'class_name'    => $class_name,
            'subject_id'    => $subject_id,
            'student_id'    => (int) $r['id'],
            'term'          => $term,
            'academic_year' => $ay,
            'components'    => $components,
            'grade_bounds'  => $bounds,
        ]);
    }
}
