<?php
// ============================================================
// Missed Attendance Remark — AJAX Save Handler
// POST-only endpoint. Returns JSON.
// Validates auth, class-teacher status, effective access,
// scope, date, and status whitelist before writing.
// All writes are wrapped in a transaction (atomic).
// ============================================================

include('includes/session1.php');
error_reporting(0);
include('includes/dbconnection.php');
require_once __DIR__ . '/includes/session_term_helper.php';
require_once __DIR__ . '/includes/missed_attendance_helper.php';

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

// Helper: send JSON response and exit
function jsonResponse(bool $success, string $message = '', int $httpCode = 200): void
{
    http_response_code($httpCode);
    echo json_encode(['success' => $success, 'message' => $message]);
    exit;
}

// ============================================================
// 1. Authentication
// ============================================================
if (!isset($_SESSION['sid'])) {
    jsonResponse(false, 'Unauthorized', 401);
}

$teacher_id = (int)$_SESSION['sid'];

// ============================================================
// 2. POST only
// ============================================================
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    jsonResponse(false, 'Method not allowed', 405);
}

// ============================================================
// 3. Class teacher check
// ============================================================
$ct_stmt = $con->prepare(
    "SELECT cs.class, cs.section
     FROM teacher_assignments ta
     JOIN class_section cs ON ta.class_id = cs.id
     WHERE ta.teacher_id = ? AND ta.is_class_teacher = 1
     LIMIT 1"
);
$ct_stmt->bind_param('i', $teacher_id);
$ct_stmt->execute();
$ct_row = $ct_stmt->get_result()->fetch_assoc();
$ct_stmt->close();

if (!$ct_row) {
    jsonResponse(false, 'Access denied: not a class teacher', 403);
}

$assigned_class   = $ct_row['class'];
$assigned_section = $ct_row['section'];

// ============================================================
// 4. Effective access check (three-level toggle)
// ============================================================
if (!checkMissedAttendanceAccess($con, $teacher_id, $assigned_class, $assigned_section)) {
    jsonResponse(false, 'Access denied: feature not enabled for your account', 403);
}

// ============================================================
// 5. Scope validation — submitted class/section must match assignment
// ============================================================
$post_class   = trim($_POST['class']   ?? '');
$post_section = trim($_POST['section'] ?? '');

if ($post_class !== $assigned_class || $post_section !== $assigned_section) {
    // Log the mismatch attempt
    error_log(sprintf(
        '[MissedAttendance] Scope mismatch: teacher_id=%d submitted class=%s section=%s but assigned class=%s section=%s IP=%s',
        $teacher_id, $post_class, $post_section, $assigned_class, $assigned_section,
        $_SERVER['REMOTE_ADDR'] ?? ''
    ));
    jsonResponse(false, 'Access denied: class/section mismatch', 403);
}

// Use DB-resolved values for all writes (never trust POST values)
$class   = $assigned_class;
$section = $assigned_section;

// ============================================================
// 6. Date validation — must be strictly before today
// ============================================================
$raw_date = trim($_POST['date'] ?? '');
$date_obj = DateTime::createFromFormat('Y-m-d', $raw_date);

if (!$date_obj || $date_obj->format('Y-m-d') !== $raw_date) {
    jsonResponse(false, 'Invalid date format', 400);
}

$today = new DateTime('today');
if ($date_obj >= $today) {
    jsonResponse(false, 'Date must be before today', 400);
}

$date = $date_obj->format('Y-m-d');

// ============================================================
// 7. Attendance payload validation
// ============================================================
$attendance_post = $_POST['attendance'] ?? [];

if (!is_array($attendance_post) || empty($attendance_post)) {
    jsonResponse(false, 'No attendance data submitted', 400);
}

$allowed_statuses = ['Present', 'Absent'];
$attendance = [];

foreach ($attendance_post as $raw_student_id => $raw_status) {
    $student_id = (int)$raw_student_id;
    $status     = (string)$raw_status;

    if ($student_id <= 0) {
        jsonResponse(false, 'Invalid student ID in submission', 400);
    }
    if (!in_array($status, $allowed_statuses, true)) {
        jsonResponse(false, 'Invalid status value: only Present or Absent are accepted', 400);
    }

    $attendance[$student_id] = $status;
}

// ============================================================
// 8. Resolve active session and term
// ============================================================
$stResult       = resolveCurrentSessionTerm($con);
$term_id        = $stResult['term_id']    ?: 0;
$session_id     = $stResult['session_id'] ?: 0;

// ============================================================
// 9. Transactional upsert + audit log
// ============================================================
$ip_address = $_SERVER['REMOTE_ADDR'] ?? '';

$con->begin_transaction();

try {
    // Prepared statements reused across the loop
    $fetch_stmt = $con->prepare(
        "SELECT status FROM attendance
         WHERE student_id = ? AND class = ? AND section = ? AND date = ?
         LIMIT 1"
    );

    $upsert_stmt = $con->prepare(
        "INSERT INTO attendance (student_id, class, section, term_id, session_id, date, status)
         VALUES (?, ?, ?, ?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE status = VALUES(status)"
    );

    $log_stmt = $con->prepare(
        "INSERT INTO missed_attendance_log
             (teacher_id, student_id, class, section, attendance_date, old_status, new_status, remarked_at, ip_address)
         VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), ?)"
    );

    foreach ($attendance as $student_id => $new_status) {

        // Fetch existing status (for audit log)
        $fetch_stmt->bind_param('isss', $student_id, $class, $section, $date);
        $fetch_stmt->execute();
        $existing = $fetch_stmt->get_result()->fetch_assoc();
        $old_status = $existing ? $existing['status'] : null;

        // Upsert attendance record
        $upsert_stmt->bind_param('issiiiss',
            $student_id, $class, $section, $term_id, $session_id, $date, $new_status, $new_status
        );
        $upsert_stmt->execute();

        // Write audit log row if status changed or was previously unset
        if ($old_status !== $new_status) {
            $log_stmt->bind_param('iissssss',
                $teacher_id, $student_id, $class, $section,
                $date, $old_status, $new_status, $ip_address
            );
            $log_stmt->execute();
        }
    }

    $fetch_stmt->close();
    $upsert_stmt->close();
    $log_stmt->close();

    $con->commit();
    jsonResponse(true, 'Attendance saved successfully');

} catch (Throwable $e) {
    $con->rollback();
    error_log('[MissedAttendance] Transaction failed: ' . $e->getMessage());
    jsonResponse(false, 'A database error occurred. No changes were saved.', 500);
}
