<?php
include "../../php/dbconnect.php";
header('Content-Type: application/json');

// Initialize response
$response = ['success' => false, 'html' => '', 'errors' => []];

// Check for a valid database connection
if (!isset($con) || !$con) {
    $response['errors'][] = 'Database connection error.';
    echo json_encode($response);
    exit;
}

function con($query) {
    global $con;
    return mysqli_query($con, $query);
}

function row($query) {
    return mysqli_fetch_assoc($query);
}

$settings = row(con("SELECT * FROM settings_v3 WHERE id = 1"));

// Retrieve POST data
$course = mysqli_real_escape_string($con, $_POST['course']);
$year = mysqli_real_escape_string($con, $_POST['year']);
$exam = mysqli_real_escape_string($con, $_POST['exam']);
$student_id = isset($_POST['student_id']) ? mysqli_real_escape_string($con, $_POST['student_id']) : null;

// Fetch all courses
$coursesQuery = "SELECT id, course FROM course";
$coursesResult = mysqli_query($con, $coursesQuery);
$courses = [];
while ($courseRow = mysqli_fetch_assoc($coursesResult)) {
    $courses[$courseRow['id']] = $courseRow['course'];
}

// Helper function to retrieve grading info for each subject
function getSubjectGradingInfo($subjectId, $course, $year, $exam) {
    global $con;
    $query = "
        SELECT *
        FROM grading_v3
        WHERE class_id = '$course' AND year = '$year' AND exam_id = '$exam' AND subject_id = '$subjectId'
        LIMIT 1
    ";
    $result = mysqli_query($con, $query);
    $row = mysqli_fetch_assoc($result);
    if ($row) {
        $gradingConditions = json_decode($row['conditions'], true) ?: [];
        return [
            'max_mark' => $row['max_mark'] ?? 100,
            'cq_pass_mark' => $row['cq_pass_mark'] ?? NULL,
            'mcq_pass_mark' => $row['mcq_pass_mark'] ?? NULL,
            'practical_pass_mark' => $row['practical_pass_mark'] ?? NULL,
            'grading_conditions' => $gradingConditions,
        ];
    }
    return ['max_mark' => 100, 'grading_conditions' => []];
}

function getGradingConditions($course, $year, $exam) {
    global $con;
    $query = "
        SELECT conditions 
        FROM grading_v3 
        WHERE class_id = '$course' AND year = '$year' AND exam_id = '$exam'
        LIMIT 1
    ";
    $result = mysqli_query($con, $query);
    if (!$result) {
        return [];
    }

    $row = mysqli_fetch_assoc($result);
    
    if ($row) {
        $rawConditions = $row['conditions'];

        $cleanedJson = trim($rawConditions);
        $cleanedJson = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $cleanedJson);
        
        if (!isValidJson($cleanedJson)) {
            return [];
        }

        $decoded = json_decode($cleanedJson, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return [];
        }

        return $decoded;
    }

    return [];
}

function isValidJson($string) {
    json_decode($string);
    return (json_last_error() == JSON_ERROR_NONE);
}

$globalGradingConditions = getGradingConditions($course, $year, $exam);

// Helper function to calculate letter grade based on grading conditions
function calculateGrade($cq, $mcq, $practical, $total, $gradingConditions, $cq_pass_mark, $mcq_pass_mark, $practical_pass_mark) {
    // Check individual component pass marks if they are not null or 0
    if ($cq_pass_mark !== null && $cq_pass_mark != 0 && $cq < $cq_pass_mark) {
        return ['grade' => 'F', 'point' => '0'];
    }
    
    if ($mcq_pass_mark !== null && $mcq_pass_mark != 0 && $mcq < $mcq_pass_mark) {
        return ['grade' => 'F', 'point' => '0'];
    }
    
    if ($practical_pass_mark !== null && $practical_pass_mark != 0 && $practical < $practical_pass_mark) {
        return ['grade' => 'F', 'point' => '0'];
    }
    
    // Determine grade based on total marks if pass marks are met
    foreach ($gradingConditions as $condition) {
        if ($total >= $condition['min'] && $total <= $condition['max']) {
            return [
                'grade' => $condition['grade'],
                'point' => $condition['point']
            ];
        }
    }
    
    return ['grade' => 'F', 'point' => '0'];
}
function checkOverallGrade($subjects) {
    foreach ($subjects as $subject) {
        // If any subject has an 'F' grade, return false
        if ($subject['grade'] === 'F') {
            return false;
        }
    }
    return true;
}
function getOverallGrade($gpa) {
    $grade_id = row(con("SELECT grade_id FROM set_grade_system_v3 WHERE system_name = 'marksheet_1'"))['grade_id'];
    $grade_data = row(con("SELECT * FROM grad_point_v3 WHERE id = '$grade_id'"))['points_grades'];

    $grades = json_decode($grade_data, true); // Decode JSON to array

    if (!is_array($grades)) {
        throw new Exception('Invalid grade data format'); // Handle error case
    }

    foreach ($grades as $grade) {
        if ($gpa >= $grade['point']) {
            return $grade['grad'];
        }
    }

    return 'F'; // Fallback grade if no match found
}

function calculateGPA($totalPoints, $totalSubjects) {
    // Validate inputs
    if (!is_numeric($totalPoints) || !is_numeric($totalSubjects)) {
        return 0;
    }
    
    if ($totalSubjects <= 0) {
        return 0;
    }
    
    // Calculate GPA with 2 decimal places
    return number_format(($totalPoints / $totalSubjects), 2);
}

// Helper function to evaluate behavior based on GPA
function getBehaviorEvaluation($gpa) {
    if ($gpa >= 4.50) {
        return 'Excellent';
    } elseif ($gpa >= 4.00) {
        return 'Good';
    } elseif ($gpa >= 3.50) {
        return 'Average';
    } else {
        return 'Poor';
    }
}

// Fetch the highest score for a given subject in the same course, year, and exam
function getHighestMarks($subjectId, $course, $year, $exam) {
    global $con;
    $query = "
        SELECT MAX(total) as highest_total
        FROM exam_result_v3
        WHERE subject = '$subjectId' AND course = '$course' AND year = '$year' AND exam_id = '$exam'
    ";
    $result = mysqli_query($con, $query);
    $row = mysqli_fetch_assoc($result);
    return $row['highest_total'] ?? 0;
}

// Fetch all student data and calculate totals

$studentsData = [];
$studentsQuery = "
    SELECT s.regi AS student_id, s.sname AS student_name, s.mName AS mName, s.roll_2 AS roll_2, s.image AS image, s.fname AS fname, 
           s.course AS course_id, s.regi AS student_reg_no,
           er.subject, er.cq, er.mcq, er.practical, er.total,
           cs.subject_name, cs.4th_subject
    FROM exam_result_v3 er
    JOIN student s ON s.id = er.student_id
    JOIN course_subject cs ON cs.id = er.subject
    WHERE er.course = '$course' AND er.year = '$year' AND er.exam_id = '$exam'
";

// Modify query if a specific student_id is provided
if ($student_id) {
    $studentsQuery .= " AND s.regi = '$student_id'";
}

$studentsQuery .= " ORDER BY cs.priority";

$studentsResult = mysqli_query($con, $studentsQuery);

if (!$studentsResult) {
    $response['errors'][] = 'Error fetching student data: ' . mysqli_error($con);
    echo json_encode($response);
    exit;
}

// Aggregate student scores and calculate GPA, failed subjects, etc.
while ($row = mysqli_fetch_assoc($studentsResult)) {
    $studentId = $row['student_id'];

    if (!isset($studentsData[$studentId])) {
        $studentsData[$studentId] = [
            'student_name' => $row['student_name'],
            'mName' => $row['mName'],
            'roll_2' => $row['roll_2'],
            'fname' => $row['fname'],
            'image' => $row['image'],
            'student_reg_no' => $row['student_reg_no'],
            'course_id' => $row['course_id'],
            'subjects' => [],
            'total_marks' => 0,
            'total_points' => 0,
            'failed_subjects' => 0,
            'has_failure' => false // Track if there is any failed subject
        ];
    }

    // Get grading info for the subject
    $subjectGradingInfo = getSubjectGradingInfo($row['subject'], $course, $year, $exam);
    $maxMark = $subjectGradingInfo['max_mark'];
    $gradingConditions = $subjectGradingInfo['grading_conditions'];

    $cq_pass_mark = $subjectGradingInfo['cq_pass_mark'];
    $mcq_pass_mark = $subjectGradingInfo['mcq_pass_mark'];
    $practical_pass_mark = $subjectGradingInfo['practical_pass_mark'];
    // Fetch the highest mark for the subject
    $highestMark = getHighestMarks($row['subject'], $course, $year, $exam);

    // Calculate grade
    $gradeData = calculateGrade($row['cq'], $row['mcq'], $row['practical'], $row['total'], $gradingConditions, $cq_pass_mark, $mcq_pass_mark, $practical_pass_mark);
    $isFourthSubject = $row['4th_subject'] == 1;

    // Check if this subject has a failing grade
    if ($gradeData['grade'] === 'F') {
        $studentsData[$studentId]['has_failure'] = true; // Mark student as having a failure
    }

    // Count failed non-4th subjects
    if ($gradeData['grade'] === 'F' && !$isFourthSubject) {
        $studentsData[$studentId]['failed_subjects']++;
    }

    // Add subject data to student's record
    $studentsData[$studentId]['subjects'][] = [
        'subject_name' => $row['subject_name'],
        'cq' => $row['cq'],
        'mcq' => $row['mcq'],
        'practical' => $row['practical'],
        'total' => $row['total'],
        'grade' => $gradeData['grade'],
        'point' => $gradeData['point'],
        'max_mark' => $maxMark,
        'highest_mark' => $highestMark
    ];

    // Update total marks and points
    $studentsData[$studentId]['total_marks'] += $row['total'];
    $studentsData[$studentId]['total_points'] += $gradeData['point'];
}

// Calculate class position based on total marks
usort($studentsData, function($a, $b) {
    return $b['total_marks'] <=> $a['total_marks'];
});
$positionMap = [];
$position = 1;
foreach ($studentsData as $studentId => $student) {
    $positionMap[$studentId] = $position++;
}

// Generate the HTML for each student's certificate
$htmlOutputArray = [];
foreach ($studentsData as $studentId => $student) {

      // Start religion calculation
      $filteredSubjects = [];
      $totalPoints = 0;
      $totalMarks = 0;
      
      // Fetch the student's religion
      $religion = row(con("SELECT `religion` FROM student WHERE regi = '{$student['student_reg_no']}'"))['religion'];
      
      // Filter subjects based on religion
      foreach ($student['subjects'] as $subject) {
          // Fetch the subject's associated religion
          $subjectReligionQuery = "SELECT religion FROM course_subject WHERE subject_name = '" . mysqli_real_escape_string($con, $subject['subject_name']) . "'";
          $subjectReligionResult = row(con($subjectReligionQuery));
          $subjectReligion = $subjectReligionResult['religion'] ?? '';
      
          // Include the subject if it has no religion requirement or matches the student's religion
          if ($subjectReligion === '' || $subjectReligion === $religion) {
              $filteredSubjects[] = $subject;
              $totalPoints += floatval($subject['point']);
              $totalMarks += floatval($subject['total']);
          }
      }
      
      // Update student data with filtered subjects
      $student['subjects'] = $filteredSubjects;
      $student['total_points'] = $totalPoints;
      $student['total_marks'] = $totalMarks;
      
      // Recalculate failed subjects
      $failedSubjects = 0;
      foreach ($filteredSubjects as $subject) {
          if ($subject['grade'] === 'F') {
              $failedSubjects++;
          }
      }
      $student['failed_subjects'] = $failedSubjects;
      // END religion calculation
  
    $course_name = $courses[$student['course_id']] ?? 'Unknown';
    $totalSubjects = count($student['subjects']);

    $gpa = calculateGPA($student['total_points'], $totalSubjects);

    $passed = checkOverallGrade($student['subjects']);

    if (!$passed) {
        $gpa = 0.00;
        $overallGrade = 'F';
    } else {
        $overallGrade = getOverallGrade($gpa);
    }
    $behaviorEvaluation = getBehaviorEvaluation($gpa);
    $classPosition = $positionMap[$studentId];
    $failedSubjects = $student['failed_subjects'];
    $date = date('Y-m-d H:i:s');

    // Generate QR code data
    $domain = $_SERVER['HTTP_HOST']; // Get the current domain dynamically
    $qrData = $settings['site_url'] . "/resultcontrol/student_info.php?data=" . base64_encode(json_encode([
        'student_id' => $student['student_reg_no'],
        'exam_id' => $exam,
        'year' => $year,
        'course' => $course,
    ]));    

    ob_start();
    QRcode::png($qrData, null, QR_ECLEVEL_L, 1);
    $qrCodeImage = ob_get_contents();
    ob_end_clean();
    $qrCodeBase64 = base64_encode($qrCodeImage);

    $exam_v3_name = row(con("SELECT exam_name FROM exam_v3 WHERE id = '$exam'"))['exam_name'];

    $student_reg_no = $student['student_reg_no'];

    $studentHtml = "
        <div class='containerrr m-3'>
        <div class='containerr' id='containerdiv'>
            <div class='header-section'>
                <h3>{$settings['website_name']}</h3>
                <h5>{$settings['address']}</h5>
            </div>
            <div class='fixed-row'>
                <div class='fixed-col'>
                         <img src='../stuImages/{$student['image']}' width='140px' style='border: 1px solid #111; width: 150px; height: 150px;' >
                </div>
                <div class='fixed-col' id='text-center'>
                    <img src='../resultcontrol/images/{$settings['logo']}' width='110px' alt='School Logo'>
                </div>
                <div class='fixed-col d-flex justify-content-end' id='text-right'>
                    <table class='grading-table'>
                        <tr class='highlight'><th>Range</th><th>Grade</th><th>GPA</th></tr>";
                        foreach ($globalGradingConditions as $condition) {
                            $studentHtml .= "<tr><td>{$condition['min']}-{$condition['max']}</td><td>{$condition['grade']}</td><td>{$condition['point']}</td></tr>";
                        }
                    $studentHtml .= "</table>
                </div>
            </div>
            <br/>
            <div class='info-section fixed-row'>
                <div class='fixed-col'>
                    
                    <p><strong>Student Name:</strong> {$student['student_name']}</p>
                    <p><strong>Father's Name:</strong> {$student['fname']}</p>
                    <p><strong>Mother's Name:</strong> {$student['mName']}</p>
                    <p><strong>Student ID:</strong> {$student['student_reg_no']}</p>
                </div>
                <div class='fixed-col'>
                    <p><strong>Exam:</strong> {$exam_v3_name} - {$year}</p>
                    <p><strong>Class:</strong> {$course_name}</p>
                    <p><strong>Roll No:</strong> {$student['roll_2']}</p>
                    <p><strong>Year:</strong> {$year}</p>
                </div>
            </div>
            <table class='result-table'>
                <thead>
                    <tr class='highlight'>
                        <th class='cent' rowspan='2'>Subject</th>
                        <th class='cent' rowspan='2'>Full Marks</th>
                        <th class='cent' rowspan='2'>Highest Marks</th>
                        <th class='cent' colspan='3'>Obtained Marks</th>
                        <th class='cent' rowspan='2'>Total Marks</th>
                        <th class='cent' rowspan='2'>Letter Grade</th>
                        <th class='cent' rowspan='2'>Grade Point</th>
                    </tr>
                    <tr class='highlight'>
                       <th class='cent'>(CQ)</th>
                       <th class='cent'>(MCQ)</th>
                       <th class='cent'>(PR)</th>
                    </tr>
                </thead>
                <tbody>";
                foreach ($student['subjects'] as $subject) {
                    // Format the point value based on the conditions
                    if (strpos($subject['point'], '.') !== false) { 
                        // If the point already has a decimal
                        $parts = explode('.', $subject['point']);
                        $formattedPoint = (strlen($parts[1]) == 1) 
                            ? "{$subject['point']}0" // If single decimal place, add '0'
                            : $subject['point'];     // Else, use as is
                    } else {
                        // If the point is an integer, append '.00'
                        $formattedPoint = "{$subject['point']}.00";
                    }
                
                    $studentHtml .= "
                        <tr>
                            <td>{$subject['subject_name']}</td>
                            <td>{$subject['max_mark']}</td>
                            <td>{$subject['highest_mark']}</td>
                            <td>{$subject['cq']}</td>
                            <td>{$subject['mcq']}</td>
                            <td>{$subject['practical']}</td>
                            <td>{$subject['total']}</td>
                            <td>{$subject['grade']}</td>
                            <td>{$formattedPoint}</td>
                        </tr>";
                }
                
                

    $studentHtml .= "
                </tbody>
                <tfoot>
                    <tr class='highlight'>
                        <td>Total Exam Marks</td>
                        <td colspan='6'>{$student['total_marks']}</td>
                        <td>{$overallGrade}</td>
                        <td>{$gpa}</td>
                    </tr>
                </tfoot>
            </table>
            <div class='fixed-row' style='margin-top: 20px;'>
                <div class='fixed-col' style='margin-right: 4px;'>
                    <table class='evaluation-table'>
                        <tr><th>Result Status</th><td>" . ($failedSubjects > 0 ? 'Failed' : 'Passed') . "</td></tr>
                        <tr><th>Class Position</th><td>{$classPosition}</td></tr>
                        <tr><th>GPA (Without 4th)</th><td>{$gpa}</td></tr>
                        <tr><th>Failed Subject (S)</th><td>{$failedSubjects}</td></tr>
                        <tr><th>Working Days</th><td></td></tr>
                        <tr><th>Total Present</th><td></td></tr>
                        <tr><th>Total Leave</th><td></td></tr>
                        <tr><th>Total Absent</th><td></td></tr>
                    </table>
                </div>
                <div class='fixed-col-5' style='margin-left: 4px;'>
                    <table class='evaluation-table'>
                        <tr><th>Moral & Behavior Evaluation</th><th>Co-Curricular Activities</th></tr>
                        <tr><td>{$behaviorEvaluation}</td><td>Sports<br>Cultural Function<br>Club-Scout/Scout/BNCC<br>Math Olympiad</td></tr>
                    </table>
                    <div class='evaluation-table' style='border: 1px solid #111; height: 50px;'> 
                        <p>Comments:</p>
                    </div>
                </div>
                <div class='fixed-col-3' style='margin-left: 3px;'>
                   <img src='data:image/png;base64,{$qrCodeBase64}' alt='QR Code' width='130px' />
                </div>
            </div>
            <div class='signature-section'>
                <div style='display: flex; justify-content: space-between;'>
                    <p>Class Teacher</p>
                    <p>Head Teacher</p>
                </div>
            </div>
            
        </div>
      <div style='display: flex; justify-content: space-between; width: 100%;'>
        <p style='margin: 0;'>Published Date: {$date}</p>
    </div>


    </div>";

    // Append each student's certificate HTML to output array
    $htmlOutputArray[] = $studentHtml;
}

// Combine all student certificates
$response['html'] = implode('', $htmlOutputArray);
$response['success'] = true;

echo json_encode($response);
?>
