<?php
ini_set('display_errors', 1);

/* ================== INCLUDES ================== */
require_once '../../base_path_include.php';
require_once $base_path_to_learning_resources  . "includes/connect.php";
require_once $base_path_to_learning_resources . 'lib/function.php';
require_once $base_path_to_learning_resources . 'lib/validate_api_signature.php';
require_once $base_path_to_learning_resources . 'lib/validate_function.php';
require_once $base_path_to_learning . 'user_management/authenticate.php';
require_once $base_path_to_learning . 'admin_api/academic_session/functions/validate_faculty.php';
require_once $base_path_to_learning . 'admin_api/academic_session/functions/functions.php';
require_once $base_path_to_learning . 'functions/common_functions.php';
require_once $base_path_to_learning_resources . 'includes/specific_db_config.php';
require_once $base_path_to_learning . "vendor/autoload.php";
require_once $base_path_to_learning_resources . 'lib/bucket_functions/bucket_functions.php';
require_once $base_path_to_learning_resources . 'includes/aws_bucket_config.php';

$postdata = $_POST;



/* ================== VALIDATION ================== */
if (
    !isset($postdata['institution_id']) || !checkIfIssetAndNotEmpty($postdata['institution_id']) ||
    !isset($postdata['student_id']) || !checkIfIssetAndNotEmpty($postdata['student_id']) ||
    !isset($postdata['marksheet_id']) || !checkIfIssetAndNotEmpty($postdata['marksheet_id']) ||
    !isset($postdata['api_signature']) || !checkIfIssetAndNotEmpty($postdata['api_signature']) ||
    !isset($postdata['jwt_token']) || !checkIfIssetAndNotEmpty($postdata['jwt_token']) ||
    !isset($postdata['marks']) || !is_array($postdata['marks'])
) {
    errorreturn("All * fields are required.");
}

/* ================== SECURITY ================== */
validateApiSignature($postdata['api_signature']);
$jwt_validate = authenticate_jwt($postdata['jwt_token']);

$userid       = $jwt_validate->data->id;
$workspace_id = $jwt_validate->data->workspace_id;
$username     = $jwt_validate->data->username;
$role         = $jwt_validate->data->role;

/* ================== DB ACCESS ================== */
$specific_db_name = validateUserAccess(
    $conn_rjllearning,
    $userid,
    $role,
    $workspace_id,
    ["superadmin","admin","principal","teacher"],
    null
);

if (!$specific_db_name) {
    errorreturn('Access denied.');
}

$conn_rjllearning_specific = dynamicDbConnection($specific_db_name);

/* ================== BASIC DATA ================== */
$institution_id = $postdata['institution_id'];
$student_id     = $postdata['student_id'];
$marksheet_id   = $postdata['marksheet_id'];

/* ================== FETCH MARKSHEET ================== */
$ExecuteSqlMarksheet = $conn_rjllearning_specific->prepare(
    "SELECT * FROM marksheet WHERE id = ?"
);
$ExecuteSqlMarksheet->execute([$marksheet_id]);
$rowmarksheet = $ExecuteSqlMarksheet->fetch(PDO::FETCH_ASSOC);

if (!$rowmarksheet) {
    errorreturn("Marksheet does not exist.");
}

$templateid = $rowmarksheet['template_id'];

/* ================== FETCH STUDENT ================== */
$ExecuteSqlStudent = $conn_rjllearning_specific->prepare(
    "SELECT name, branch_id, class_id, academic_id, section_id
     FROM students WHERE id = ?"
);
$ExecuteSqlStudent->execute([$student_id]);
$rowstudent = $ExecuteSqlStudent->fetch(PDO::FETCH_ASSOC);

if (!$rowstudent) {
    errorreturn("Student does not exist.");
}

$branch      = $rowstudent['branch_id'];
$class       = $rowstudent['class_id'];
$academic_id = $rowstudent['academic_id'];
$section_id  = $rowstudent['section_id'];


/* ================== CHECK LOCK TABLE ================== */

$lock_sql = "SELECT class_id, section_id, student_list
             FROM lock_marksheet_cache
             WHERE institution_id = ?
             AND branch_id = ?
             AND marksheet_id = ?";

$lock_stmt = $conn_rjllearning_specific->prepare($lock_sql);
$lock_stmt->execute([
    $institution_id,
    $branch,
    $marksheet_id
]);

$lock_rows = $lock_stmt->fetchAll(PDO::FETCH_ASSOC);

if (!empty($lock_rows)) {

    foreach ($lock_rows as $lock_row) {

        $student_list = json_decode($lock_row['student_list'], true);

        if (!empty($student_list) && in_array((string)$student_id, $student_list)) {

            # Override class and section from lock table
            $class      = $lock_row['class_id'];
            $section_id = $lock_row['section_id'];

            break;
        }
    }
}
/* ================== DELETE OLD ================== */
$conn_rjllearning_specific->prepare(
    "DELETE FROM student_marksheet_data
     WHERE student_id = ? AND marksheet_id = ?"
)->execute([$student_id, $marksheet_id]);

/* ===================== INPUT ===================== */

$marks = array_values($postdata['marks']);
$subject_enabled = $postdata['subject_enabled'] ?? [];

/* ================== HELPERS ================== */

function numVal($v) {
    return is_numeric($v) ? (float)$v : null;
}

function validPercent($v) {
    return ($v !== null && is_numeric($v));
}

function percent30($v) {
    return is_numeric($v) ? ($v / 30) * 100 : null;
}

function percent50($v) {
    return is_numeric($v) ? ($v / 50) * 100 : null;
}

function gradeFromPercent($p) {
    if ($p >= 91) return 'A1';
    if ($p >= 81) return 'A2';
    if ($p >= 71) return 'B1';
    if ($p >= 61) return 'B2';
    if ($p >= 51) return 'C1';
    if ($p >= 41) return 'C2';
    if ($p >= 33) return 'D';
    if ($p >= 21) return 'E1';
    return 'E2';
}

/* ✅ CHANGE → NA instead of blank */
function setNARangeKeepIndex(&$arr, $from, $to) {
    for ($i = $from; $i <= $to; $i++) {
        $arr[$i] = 'NA';
    }
}

/* ================== SUBJECT ENABLE ================== */

$hindi   = !empty($subject_enabled['hindi']);
$evs     = !empty($subject_enabled['evs']);
$gk      = !empty($subject_enabled['gk']);
$drawing = !empty($subject_enabled['drawing']);

/* ================== TERM II (0–17) ================== */

if (!$hindi)   setNARangeKeepIndex($marks, 4, 7);
if (!$evs)     setNARangeKeepIndex($marks, 12, 13);
if (!$gk)      setNARangeKeepIndex($marks, 14, 15);
if (!$drawing) setNARangeKeepIndex($marks, 16, 17);

/* ---------- Periodic 3 & 4 ---------- */

$p3 = [];
$p4 = [];

/* English */
$p3[] = percent30(numVal($marks[0] ?? null));
$p3[] = percent50(numVal($marks[2] ?? null));
$p4[] = percent30(numVal($marks[1] ?? null));
$p4[] = percent50(numVal($marks[3] ?? null));

/* Hindi */
if ($hindi) {
    $p3[] = percent30(numVal($marks[4] ?? null));
    $p3[] = percent50(numVal($marks[6] ?? null));
    $p4[] = percent30(numVal($marks[5] ?? null));
    $p4[] = percent50(numVal($marks[7] ?? null));
}

/* Maths */
$p3[] = percent30(numVal($marks[8] ?? null));
$p3[] = percent50(numVal($marks[10] ?? null));
$p4[] = percent30(numVal($marks[9] ?? null));
$p4[] = percent50(numVal($marks[11] ?? null));

/* GK */
if ($gk) {
    $p3[] = percent30(numVal($marks[14] ?? null));
    $p4[] = percent30(numVal($marks[15] ?? null));
}

/* Drawing */
if ($drawing) {
    $p3[] = percent30(numVal($marks[16] ?? null));
    $p4[] = percent30(numVal($marks[17] ?? null));
}

$p3 = array_filter($p3, 'validPercent');
$p4 = array_filter($p4, 'validPercent');

$marks[18] = count($p3) ? gradeFromPercent(array_sum($p3) / count($p3)) : '';
$marks[19] = count($p4) ? gradeFromPercent(array_sum($p4) / count($p4)) : '';

/* ================== TERM I (38–55) ================== */

if (!$hindi)   setNARangeKeepIndex($marks, 42, 45);
if (!$evs)     setNARangeKeepIndex($marks, 50, 51);
if (!$gk)      setNARangeKeepIndex($marks, 52, 53);
if (!$drawing) setNARangeKeepIndex($marks, 54, 55);

$p1 = [];
$p2 = [];

/* English */
$p1[] = percent30(numVal($marks[38] ?? null));
$p1[] = percent50(numVal($marks[40] ?? null));
$p2[] = percent30(numVal($marks[39] ?? null));
$p2[] = percent50(numVal($marks[41] ?? null));

/* Hindi */
if ($hindi) {
    $p1[] = percent30(numVal($marks[42] ?? null));
    $p1[] = percent50(numVal($marks[44] ?? null));
    $p2[] = percent30(numVal($marks[43] ?? null));
    $p2[] = percent50(numVal($marks[45] ?? null));
}

/* Maths */
$p1[] = percent30(numVal($marks[46] ?? null));
$p1[] = percent50(numVal($marks[48] ?? null));
$p2[] = percent30(numVal($marks[47] ?? null));
$p2[] = percent50(numVal($marks[49] ?? null));

/* GK */
if ($gk) {
    $p1[] = percent30(numVal($marks[52] ?? null));
    $p2[] = percent30(numVal($marks[53] ?? null));
}

/* Drawing */
if ($drawing) {
    $p1[] = percent30(numVal($marks[54] ?? null));
    $p2[] = percent30(numVal($marks[55] ?? null));
}

$p1 = array_filter($p1, 'validPercent');
$p2 = array_filter($p2, 'validPercent');

$marks[56] = count($p1) ? gradeFromPercent(array_sum($p1) / count($p1)) : '';
$marks[57] = count($p2) ? gradeFromPercent(array_sum($p2) / count($p2)) : '';

/* ================== SAVE ================== */

$final_marks = array_combine(range(1, count($marks)), $marks);
$json_data = json_encode($final_marks, JSON_UNESCAPED_UNICODE);

/* ================== SAVE MARKSHEET + ANALYTICS ================== */

try {

    // 🔐 Start transaction
    $conn_rjllearning_specific->beginTransaction();

    /* ---------- INSERT MARKSHEET DATA ---------- */
    $insertStmt = $conn_rjllearning_specific->prepare("
        INSERT INTO student_marksheet_data (
            institution_id,
            marksheet_id,
            student_id,
            data,
            branch_id,
            academic_id,
            class_id,
            section_id,
            created_by,
            date_created,
            time_created,
            status
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    ");

    $insertStmt->execute([
        $institution_id,
        $marksheet_id,
        $student_id,
        $json_data,                 // ✅ contains LT safely
        $branch,
        $academic_id,
        $class,
        $section_id,
        $username,
        date("Y-m-d"),
        date("H:i:s"),
        '1'
    ]);

    // ✅ Get inserted row ID
    $lastId = $conn_rjllearning_specific->lastInsertId();

    if (!$lastId) {
        throw new Exception("Failed to insert marksheet data.");
    }

    /* ---------- GENERATE ANALYTICS (LT-SAFE) ---------- */
    $analytics = marksheet_analytics_32_store_all($json_data);

    /* ---------- UPDATE ANALYTICS ---------- */
    $updateStmt = $conn_rjllearning_specific->prepare("
        UPDATE student_marksheet_data
        SET analytics = ?
        WHERE id = ?
    ");

    $updateStmt->execute([
        json_encode($analytics, JSON_UNESCAPED_UNICODE),
        $lastId
    ]);

    // ✅ Commit transaction
    $conn_rjllearning_specific->commit();

    successreturn("Marksheet saved successfully.");

} catch (Exception $e) {

    // ❌ Rollback on any failure
    $conn_rjllearning_specific->rollBack();

    errorreturn("Failed to save marksheet: " . $e->getMessage());
}
function marksheet_analytics_32($json)
{
    $data = json_decode($json, true);
    if (!is_array($data)) {
        return ['error' => 'Invalid marks data'];
    }

    // normalize keys to int
    $data = array_combine(
        array_map('intval', array_keys($data)),
        array_values($data)
    );

    /* ✅ numeric only, LT / "" / null ignored */
    $num = function ($v) {
        return is_numeric($v) ? (float)$v : null;
    };

    $gradeFromPercent = function ($percent) {
        if ($percent >= 91) return 'A1';
        if ($percent >= 81) return 'A2';
        if ($percent >= 71) return 'B1';
        if ($percent >= 61) return 'B2';
        if ($percent >= 51) return 'C1';
        if ($percent >= 41) return 'C2';
        if ($percent >= 33) return 'D';
        if ($percent >= 21) return 'E1';
        return 'E2';
    };

    /* ================= EXAM DETECTION ================= */

    $has_unit2  = isset($data[1]) || isset($data[3]);
    $has_unit1  = isset($data[39]) && !isset($data[40]);
    $has_term1  = isset($data[39]) && isset($data[40]);
    $has_final  = $has_unit2 && ($has_unit1 || $has_term1);

    if ($has_final) {
        $use_p3p4 = range(0, 17);
        $use_p1p2 = range(38, 55);
    } elseif ($has_term1) {
        $use_p3p4 = [];
        $use_p1p2 = range(38, 56);
    } elseif ($has_unit1) {
        $use_p3p4 = [];
        $use_p1p2 = [38,39,42,43,46,47,50,52,54];
    } elseif ($has_unit2) {
        $use_p3p4 = range(0, 17);
        $use_p1p2 = [];
    } else {
        return ['error' => 'Unable to detect exam type'];
    }

    /* ================= SUBJECT CONFIG ================= */

    $subjects = [
        'English' => ['idx' => [0,1,2,3],   'max' => 320],
        'Hindi'   => ['idx' => [4,5,6,7],   'max' => 320],
        'Maths'   => ['idx' => [8,9,10,11], 'max' => 320],
        'EVS'     => ['idx' => [12,13],     'max' => 120],
        'GK'      => ['idx' => [14,15],     'max' => 120],
        'Drawing' => ['idx' => [16,17],     'max' => 120],
    ];

    $subjectRankings = [];
    $marksObtained = 0;
    $totalMax = 0;

    /* ================= CALCULATION ================= */

    foreach ($subjects as $subject => $cfg) {

        $total = 0;
        $hasAnyMark = false;

        // TERM II (0–17)
        foreach ($use_p3p4 as $i) {
            if (in_array($i, $cfg['idx'])) {
                $val = $num($data[$i + 1] ?? null);
                if ($val !== null) {
                    $total += $val;
                    $hasAnyMark = true;
                }
            }
        }

        // TERM I (38–55)
        foreach ($use_p1p2 as $i) {
            $i0 = $i - 38;
            if (in_array($i0, $cfg['idx'])) {
                $val = $num($data[$i + 1] ?? null);
                if ($val !== null) {
                    $total += $val;
                    $hasAnyMark = true;
                }
            }
        }

        // ❌ completely skip if only LT / blanks
        if (!$hasAnyMark) continue;

        $percent = round(($total / $cfg['max']) * 100, 2);
        $grade = $gradeFromPercent($percent);

        $marksObtained += $total;
        $totalMax += $cfg['max'];

        $subjectRankings[] = [
            'subject' => $subject,
            'total' => round($total, 2),
            'percentage' => $percent,
            'grade' => $grade
        ];
    }

    usort($subjectRankings, fn($a, $b) => $b['total'] <=> $a['total']);

    $overallPercent = $totalMax > 0
        ? round(($marksObtained / $totalMax) * 100, 2)
        : 0;

    return [
        'total_obtained' => round($marksObtained, 2),
        'total_max' => $totalMax,
        'percentage' => $overallPercent,
        'grade' => $gradeFromPercent($overallPercent),
        'highest_marks_obtained_subject' => $subjectRankings[0]['subject'] ?? null,
        'lowest_marks_obtained_subject' => end($subjectRankings)['subject'] ?? null,
        'subject_rankings' => $subjectRankings
    ];
}

function marksheet_analytics_32_store_all($json)
{
    $data = json_decode($json, true);
    if (!is_array($data)) {
        return ['error' => 'Invalid marks data'];
    }

    // helper to filter keys
    $only = function ($keys) use ($data) {
        $out = [];
        foreach ($keys as $k) {
            if (isset($data[$k])) {
                $out[$k] = $data[$k];
            }
        }
        return json_encode($out, JSON_UNESCAPED_UNICODE);
    };

    // 🔹 key maps (from HTML)
    $unit2_keys = [1,3,5,7,9,11,13,15,17];
    $unit1_keys = [39,41,43,45,47,49,51,53,55];
    $term1_keys = [39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56];
    $final_keys = array_merge(range(1,17), range(39,56));

    return [
        'p1' => array_merge(
            ['label' => 'Unit 1'],
            marksheet_analytics_32($only($unit1_keys))
        ),
        'p2' => array_merge(
            ['label' => 'Term 1'],
            marksheet_analytics_32($only($term1_keys))
        ),
        'p3' => array_merge(
            ['label' => 'Unit 2'],
            marksheet_analytics_32($only($unit2_keys))
        ),
        'final' => array_merge(
            ['label' => 'Final'],
            marksheet_analytics_32($only($final_keys))
        )
    ];
}