<?php
declare(strict_types=1);

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

require_once __DIR__ . '/../includes/config.php';
require_once __DIR__ . '/../includes/db.php';
require_once __DIR__ . '/../includes/functions.php';
require_once __DIR__ . '/../includes/teacher-auth.php';
require_once __DIR__ . '/../includes/teacher-course-context.php';
require_once __DIR__ . '/../includes/grade-engine.php';

$pdo = db();

if (!isPost()) {
    jsonResponse(['success' => false, 'message' => 'Method not allowed.'], 405);
}
if (!isTeacherLoggedIn()) {
    jsonResponse(['success' => false, 'message' => 'Unauthorized.'], 401);
}
if (!verifyCsrf()) {
    jsonResponse(['success' => false, 'message' => 'The security token is invalid or expired.'], 419);
}

$teacher = currentTeacher($pdo);
if (!$teacher) {
    jsonResponse(['success' => false, 'message' => 'Teacher account was not found.'], 401);
}

$studentId = (int)($_POST['student_id'] ?? 0);
$courseId = (int)($_POST['course_id'] ?? 0);
$itemId = (int)($_POST['item_id'] ?? 0);
$title = trim((string)($_POST['title'] ?? ''));
$type = strtolower(trim((string)($_POST['type'] ?? $_POST['item_type'] ?? 'extra')));
$score = (float)($_POST['score'] ?? 0);
$maxScore = (float)($_POST['max_score'] ?? 100);
$weight = (float)($_POST['weight'] ?? $_POST['weight_percent'] ?? 0);
$notes = trim((string)($_POST['notes'] ?? $_POST['feedback'] ?? ''));

$aliases = ['quiz' => 'exam', 'project' => 'extra', 'stars' => 'participation', 'obstacles' => 'obstacle'];
$type = $aliases[$type] ?? $type;
$allowedTypes = ['exam','homework','participation','attendance','vocabulary','shadowing','obstacle','extra'];

if ($studentId <= 0 || $courseId <= 0 || $title === '' || !in_array($type, $allowedTypes, true)) {
    jsonResponse(['success' => false, 'message' => 'Invalid grade data.'], 422);
}
if ($maxScore <= 0 || $score < 0 || $score > $maxScore || $weight < 0 || $weight > 100) {
    jsonResponse(['success' => false, 'message' => 'Score, maximum score, or weight is outside the allowed range.'], 422);
}
if (!teacherCanAccessStudentCourse($pdo, (int)$teacher['id'], $studentId, $courseId)) {
    jsonResponse(['success' => false, 'message' => 'You cannot grade this student in the selected course.'], 403);
}

try {
    $saved = saveStudentGrade(
        $pdo,
        $studentId,
        $courseId,
        $type,
        $itemId,
        $title,
        $score,
        $maxScore,
        $weight,
        $notes !== '' ? $notes : null,
        (int)$teacher['id'],
        null
    );
    if (!$saved) {
        jsonResponse(['success' => false, 'message' => 'The grade could not be saved. Run the database upgrade script first.'], 500);
    }
    $final = getStudentFinalGrade($pdo, $studentId, $courseId);
    logActivity($pdo, 'teacher', (int)$teacher['id'], 'Grade saved', "Saved {$type} grade for student {$studentId} in course {$courseId}.");
    jsonResponse([
        'success' => true,
        'message' => 'Grade saved successfully.',
        'percentage' => round(($score / $maxScore) * 100, 2),
        'final_grade' => round((float)($final['final_percentage'] ?? 0), 2),
        'grade_letter' => (string)($final['grade_letter'] ?? gradeLetter((float)($final['final_percentage'] ?? 0))),
    ]);
} catch (Throwable $e) {
    error_log('[SMI save grade] ' . $e->getMessage());
    jsonResponse(['success' => false, 'message' => APP_DEBUG ? $e->getMessage() : 'Failed to save the grade.'], 500);
}
