<?php

/**
 * Result Management System for Institutions
 *
 * Copyright (C) 2025 ASTGD
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

/**
 * Prevent direct access to the file.
 *
 * This code checks if the constant 'ABSPATH' is defined. If it is not defined,
 * it means the file is being accessed directly, and the script will exit.
 *
 * 'ABSPATH' is a constant defined by WordPress, which represents the absolute
 * path to the WordPress directory. By checking for this constant, we ensure
 * that the file is being accessed within the context of a WordPress installation.
 */
if (! defined('ABSPATH')) {
	exit;
}

/**
 * Class ASTGDRMSYS_StudentRecordManager
 *
 * This class is responsible for managing student records within the Mystical Playground WordPress plugin.
 * It provides functionalities to add, update, delete, and retrieve student records.
 *
 * @package ResultManagementSystem
 * @since 1.0.0
 */
class ASTGDRMSYS_StudentRecordManager
{

	private $wpdb;
	private $prefix;

	/**
	 * Constructor for the class.
	 *
	 * This method is called when an instance of the class is created.
	 */
	public function __construct()
	{
		global $wpdb;
		$this->wpdb   = $wpdb;
		$this->prefix = $wpdb->prefix;

		// Handle form submissions
		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') {
			// Check if the nonce is set and valid
			if (isset($_POST['add_student_nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['add_student_nonce'])), 'add_student_action')) {
				// Check which form was submitted
				if (isset($_POST['submit'])) {
					$this->handleAddRecord();
				} elseif (isset($_POST['submitcsv'])) {
					$this->handleCSVUpload();
				}
			}
		}
	}

	/**
	 * Displays the student record addition form or interface.
	 *
	 * This method is responsible for rendering the necessary HTML and other
	 * elements to allow users to add a new student record.
	 *
	 * @return void
	 */
	public function astgdrmsys_display()
	{
		$this->displaySuccessMessage();
		echo '<div class="container">';
		$this->renderAddRecordForm();
		$this->renderCSVUploadForm();
		echo '</div>';
	}

	/**
	 * Displays a success message to the user.
	 *
	 * This function is responsible for rendering a success message
	 * when a student record is successfully added.
	 *
	 * @return void
	 */
	private function displaySuccessMessage()
	{
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		if (isset($_GET['redirect']) && $_GET['redirect'] === 'success') {
			echo '<div id="message_div" class="alert alert-success">
                <div style="text-align: center; color: #2ecc71; font-weight: 600; padding: 15px; background: #eaffea; border-radius: 8px; margin-bottom: 20px;">Student Record Added Successfully</div>
                <button class="close-message" onclick="this.parentElement.style.display=\'none\';">&times;</button>
            </div>';
		}
	}

	/**
	 * Renders the form for adding a new student record.
	 *
	 * This function generates and displays the HTML form that allows users to input
	 * and submit new student records into the system.
	 *
	 * @return void
	 */
	private function renderAddRecordForm()
{ 
    // Fetch the default labels from the new separate option
    $custom_field_labels = get_option('astgdrmsys_custom_field_labels', []);
    ?>
    <div id="adddiv">
        <div class="premium-page-header">
            <div class="page-header-text">
                <h1><?php esc_html_e('Add Student Result', 'result-management-system-for-institutions'); ?></h1>
                <p><?php esc_html_e('Insert a single student result record manually.', 'result-management-system-for-institutions'); ?></p>
            </div>
        </div>
        <form action="" method="POST" enctype="multipart/form-data">
            <?php wp_nonce_field('add_student_action', 'add_student_nonce'); ?>
            <div class="student-actions-container">
                <div class="action-row">
                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
                        <div class="filter-field">
                            <label for="sno"><strong>Roll Number :</strong></label>
                            <input type="text" placeholder="Enter Serial Number" name="sno" id="sno" required>
                        </div>
                        <div class="filter-field">
                            <label for="regno"><strong>Registration No :</strong></label>
                            <input type="text" placeholder="Enter Registration Number" name="regno" id="regno" required>
                        </div>
                        <div class="filter-field">
                            <label for="name"><strong>Name :</strong></label>
                            <input type="text" placeholder="Enter Student Name" required name="name" id="name">
                        </div>
                        <div class="filter-field">
                            <label><strong>Gender :</strong></label>
                            <div class='gender' style="display: flex; gap: 15px; align-items: center; margin-top: 5px;">
                                <div><input type="radio" id="male" name="gender" value="MALE" required> <label for="male">Male</label></div>
                                <div><input type="radio" id="female" name="gender" value="FEMALE" required> <label for="female">Female</label></div>
                                <div><input type="radio" id="other" name="gender" value="OTHERS" required> <label for="other">Others</label></div>
                            </div>
                        </div>
                        <div class="filter-field">
                            <label for="fname"><strong>Father's Name :</strong></label>
                            <input type="text" placeholder="Enter Father's Name" name="fname" id="fname">
                        </div>
                        <div class="filter-field">
                            <label for="mname"><strong>Mother's Name :</strong></label>
                            <input type="text" placeholder="Enter Mother's Name" name="mname" id="mname">
                        </div>
                        <div class="filter-field">
                            <label><strong>Class :</strong></label>
                            <select name="class" class="selectClass" id="selectClass" required>
                                <option value="">Select Class</option>
                                <?php $this->renderClassOptions(); ?>
                            </select>
                        </div>
                        <div class="filter-field">
                            <label><strong>Department :</strong></label>
                            <select name="department" class="selectDepartment" id="selectDepartment" required>
                                <option value="">Select Class First</option>
                            </select>
                        </div>
                        <div class="filter-field">
                            <label><strong>Section :</strong></label>
                            <select name="section" class="selectSection" required>
                                <option value="">Select Dept First</option>
                            </select>
                        </div>
                        <div class="filter-field">
                            <label><strong>Select Exam:</strong></label>
                            <select name="exam_name" class="selectExam" required>
                                <option value="">Select Class First</option>
                            </select>
                        </div>
                        <div class="filter-field">
                            <label for="is_absent"><strong>Is Absent :</strong></label>
                            <div style="margin-top: 5px;">
                                <input type="checkbox" name="is_absent" id="is_absent" value="1">
                            </div>
                        </div>
                        <div class="filter-field">
                            <label for="student_image"><strong>Student Image:</strong></label>
                            <input type="file" name="student_image" id="student_image" accept="image/jpeg,image/png,image/jpg" style="padding: 8px; border: 1px solid #e2e8f0; border-radius: 4px; background: #f8fafc; width: 100%;">
                            <p class="description" style="margin-top: 5px;">Accepted formats: JPG, JPEG, PNG. Max size: 2MB.</p>
                        </div>
                    </div>

                    <div style="margin-top: 20px; border-top: 1px solid #e2e8f0; padding-top: 20px;">
                        <h3 style="margin-bottom: 15px;">Custom Fields</h3>
                        <div style="display: grid; grid-template-columns: 1fr; gap: 15px;">
                            <?php foreach ($custom_field_labels as $index => $label) : 
                                $field_number = $index + 1; ?>
                                <div style="display: grid; grid-template-columns: 1fr 2fr; gap: 20px; align-items: end;">
                                    <div class="filter-field">
                                        <label for="custom_field_name_<?php echo esc_attr($index); ?>">
                                            <strong>Custom Field <?php echo esc_html($field_number); ?> Name:</strong>
                                        </label>
                                        <input id="custom_field_name_<?php echo esc_attr($index); ?>" type="text" name="custom_fields[<?php echo esc_attr($index); ?>][name]" value="<?php echo esc_attr($label); ?>" class="regular-text">
                                    </div>
                                    <div class="filter-field">
                                        <label for="custom_field_value_<?php echo esc_attr($index); ?>">
                                            <strong>Custom Field <?php echo esc_html($field_number); ?> Value:</strong>
                                        </label>
                                        <input id="custom_field_value_<?php echo esc_attr($index); ?>" type="text" name="custom_fields[<?php echo esc_attr($index); ?>][value]" placeholder="Enter value for <?php echo esc_attr($label); ?>" class="regular-text" style="width: 100%;">
                                    </div>
                                </div>
                            <?php endforeach; ?>
                            
                            <?php if (empty($custom_field_labels)) : ?>
                                <div class="custom-display-td" style="padding: 15px; background: #f8fafc; border-radius: 6px;">
                                    <p class="custom-display-text" style="margin-bottom: 5px;">No default custom fields are configured.</p>
                                    <p class="custom-display-url">
                                        <a href="<?php echo esc_url( admin_url( 'admin.php?page=astgdrmsys-settings&option=display_name' ) ); ?>">
                                            Add fields in the Settings Page
                                        </a>.
                                    </p>
                                </div>
                            <?php endif; ?>
                        </div>
                    </div>
                    
                    <div style="margin-top: 25px;">
                        <input class="btn btn-primary hero-btn" type="submit" name='submit' value="Submit" style="width: auto; padding: 0 30px;">
                    </div>
                </div>
            </div>
        </form>
    </div> <?php
}

	/**
	 * Renders the options for the class selection dropdown.
	 *
	 * This function generates and outputs the HTML for the class options
	 * in a dropdown menu. It is used in the student record addition form
	 * to allow users to select a class for the student.
	 *
	 * @return void
	 */
	private function renderClassOptions()
	{
		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$classes = $this->wpdb->get_results("SELECT * FROM `{$this->prefix}astgdrmsys_class`", ARRAY_A);
		foreach ($classes as $class) {
			// Convert $class to array if it's an object
			if (is_object($class)) {
				$class = (array) $class;
			}
			echo "<option value='" . esc_html($class['id']) . "'>" . esc_html($class['class']) . '</option>';
		}
	}

	/**
	 * Renders the CSV upload form for adding student records.
	 *
	 * This function generates the HTML form that allows users to upload a CSV file
	 * containing student records. The uploaded file will be processed and the
	 * student records will be added to the system.
	 *
	 * @return void
	 */
	private function renderCSVUploadForm()
	{	?>
		<div align="center" id="div">
			<div class="premium-page-header" id="csvheading" style="margin-top: 40px;">
				<div class="page-header-text">
					<h1><?php esc_html_e('Add Records Using CSV', 'result-management-system-for-institutions'); ?></h1>
					<p><?php esc_html_e('Upload a CSV file to insert multiple student records.', 'result-management-system-for-institutions'); ?></p>
				</div>
			</div>
			<form method="post" action="" enctype="multipart/form-data" class="add-record-form">
				<?php wp_nonce_field('add_student_action', 'add_student_nonce'); ?>
				<div style="background: #ffffff; padding: 25px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.02); border: 1px solid #e2e8f0; margin: 20px auto; max-width: 500px; text-align: left;">
					<label style="display: block; font-size: 13px; font-weight: 600; color: #1e293b; margin-bottom: 12px;"><?php esc_html_e('Choose CSV file', 'result-management-system-for-institutions'); ?></label>
					<div class="file-field" style="margin-bottom: 20px;">
						<input type="file" name="file" id="CSV_file" required style="width: 100%; padding: 8px; border: 1px solid #e2e8f0; border-radius: 4px; background: #f8fafc;">
					</div>
					<input class="btn btn-primary hero-btn" type="submit" name="submitcsv" value="Import" id="import" style="width: 100%;">
				</div>
				<!-- message and redirect link -->
				<span class="text-info">
					* Download CSV format from 
					<a class="custom-display-url" href="<?php echo admin_url('admin.php?page=astgdrmsys-generate-bulk-csv'); ?>">
						<strong>Generate CSV</strong>
					</a>
				</span>
			</form>
			<h5 style="display: none;">Note: <a id="read" href="<?php echo esc_url(admin_url('admin.php?page=astgdrmsys-help#import')); ?>">Read this</a> before uploading csv file</h5>
		</div> <?php
	}
	
	/**
	 * Handles the addition of a new student record.
	 *
	 * This function processes the input data for adding a new student record
	 * and performs necessary validation and database operations.
	 *
	 * @return void
	*/
	private function handleAddRecord()
	{
		$data = $this->sanitizeInputData();

		if (is_wp_error($data)) {
			wp_die(esc_html($data->get_error_message()));
		}

		$data = $this->attachStudentDatabaseLinks($data);
		
		$added = $this->wpdb->insert(
		$this->prefix . 'astgdrmsys_student_result',
				$data,
				array_fill(0, count($data), '%s')
			);

		if ($added) {
			wp_safe_redirect(admin_url('admin.php?page=astgdrmsys-add-record&redirect=success'));
			exit;
		}
	}
	/**
	 * Customizes the upload directory for student images.
	 *
	 * This function modifies the upload directory structure to include a subdirectory
	 * based on the current year and month, specifically for storing student images.
	 *
	 * @param array $dirs The original upload directory information.
	 * @return array The modified upload directory information with a custom subdirectory.
	 */
	public function astgdrmsys_custom_upload_dir($dirs) {
		$time = current_time('mysql');
		$y = date('Y', strtotime($time));
		$m = date('m', strtotime($time));
	
		$subdir = "/$y/$m/student-image";
	
		$dirs['subdir'] = $subdir;
		$dirs['path']   = $dirs['basedir'] . $subdir;
		$dirs['url']    = $dirs['baseurl'] . $subdir;
	
		return $dirs;
	}
	
	/**
	 * Sanitize input data from the POST request.
	 *
	 * This function sanitizes various fields from the POST request to ensure that
	 * the data is safe to use. It splits the 'exam_name' field to extract the
	 * 'exam_year' and returns an associative array with sanitized values.
	 *
	 * @return array An associative array containing sanitized input data:
	 *               - 'sno' (string): The sanitized serial number.
	 *               - 'regno' (string): The sanitized registration number.
	 *               - 'name' (string): The sanitized name.
	 *               - 'username' (string): The sanitized username.
	 *               - 'gender' (string): The sanitized gender.
	 *               - 'fname' (string): The sanitized father's name.
	 *               - 'mname' (string): The sanitized mother's name.
	 *               - 'class' (string): The sanitized class.
	 *               - 'department' (string): The sanitized department.
	 *               - 'section' (string): The sanitized section.
	 *               - 'exam_name' (string): The sanitized exam name.
	 *               - 'exam_year' (string): The sanitized exam year.
	 */
	private function sanitizeInputData()
	{
		// Verify nonce before processing POST data
		if (
			! isset($_POST['add_student_nonce']) ||
			! wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['add_student_nonce'])), 'add_student_action')
		) {
			return new WP_Error('invalid_nonce', 'Security check failed.');
		}

		if ( isset($_FILES['student_image']) && ! empty($_FILES['student_image']['name']) ) {
		
			// Add filter to customize upload path
			add_filter('upload_dir', array($this, 'astgdrmsys_custom_upload_dir'));
		
			$uploadedfile     = $_FILES['student_image'];
			$upload_overrides = array( 'test_form' => false );
		
			$movefile = wp_handle_upload( $uploadedfile, $upload_overrides );
		
			// Remove the filter after upload is done
			remove_filter('upload_dir', array($this, 'astgdrmsys_custom_upload_dir'));
		
			if ( $movefile && ! isset($movefile['error']) ) {
				// Success - save the URL or file path to DB
				$student_image_url = esc_url_raw($movefile['url']);
				$_POST['student_image'] = $student_image_url;
			} elseif ( isset($movefile['error']) ) {
				$error_message = esc_html__('Error uploading student image: ', 'result-management-system-for-institutions') . $movefile['error'];
				do_action('astgdrmsys_log_error', $error_message);
				return new WP_Error('upload_error', esc_html__('Error uploading student image.', 'result-management-system-for-institutions'));
			} else {
				$error_message = $movefile['error'];
				do_action('astgdrmsys_log_error', esc_html__('Error uploading student image: ', 'result-management-system-for-institutions') . $error_message);
				return new WP_Error('upload_error', esc_html__('Error uploading student image.', 'result-management-system-for-institutions'));
			}
		}	

		$exam_name_raw = isset($_POST['exam_name']) ? sanitize_text_field(wp_unslash($_POST['exam_name'])) : '';
		$array         = explode(',', $exam_name_raw); // Splitting exam_year from exam_name
		$exam_name     = $array[0] ?? '';
		$exam_year     = $array[1] ?? '';
		$is_absent = isset($_POST['is_absent']) ? 1 : 0;
		$remark    = $is_absent ? 'ABSENT' : '';
		
		$custom_fields_data = [];
		// check for custom fields
		if (isset($_POST['custom_fields']) && is_array($_POST['custom_fields'])) {
			foreach ($_POST['custom_fields'] as $field_pair) {
				// Only save the pair if BOTH the name and value are filled out
				if (isset($field_pair['name'], $field_pair['value']) && !empty($field_pair['name']) && !empty($field_pair['value'])) {
					$custom_fields_data[] = [
						'name'  => sanitize_text_field(wp_unslash($field_pair['name'])),
						'value' => sanitize_text_field(wp_unslash($field_pair['value'])),
					];
				}
			}
		}

		return array(
			'sno'        => isset($_POST['sno']) ? sanitize_text_field(wp_unslash($_POST['sno'])) : '',
			'regno'      => isset($_POST['regno']) ? sanitize_text_field(wp_unslash($_POST['regno'])) : '',
			'name'       => isset($_POST['name']) ? sanitize_text_field(wp_unslash($_POST['name'])) : '',
			'gender'     => isset($_POST['gender']) ? sanitize_text_field(wp_unslash($_POST['gender'])) : '',
			'fname'      => isset($_POST['fname']) ? sanitize_text_field(wp_unslash($_POST['fname'])) : '',
			'mname'      => isset($_POST['mname']) ? sanitize_text_field(wp_unslash($_POST['mname'])) : '',
			'remark'     => $remark,
			'class'      => isset($_POST['class']) ? sanitize_text_field(wp_unslash($_POST['class'])) : '',
			'department' => isset($_POST['department']) ? sanitize_text_field(wp_unslash($_POST['department'])) : '',
			'section'    => isset($_POST['section']) ? sanitize_text_field(wp_unslash($_POST['section'])) : '',
			'exam_name'  => $exam_name,
			'exam_year'  => $exam_year,
			'is_absent'  => $is_absent,
			'student_image' => isset($_POST['student_image']) ? sanitize_text_field($_POST['student_image']) : '',
			'custom_fields' => wp_json_encode($custom_fields_data), // Add custom fields data
		);
	}
	
	/**
	 * Handles the CSV file upload process.
	 *
	 * This function processes the uploaded CSV file, validates its contents,
	 * and performs necessary actions to store or update student records.
	 *
	 * @return void
	*/
	private function handleCSVUpload()
	{
		// Verify nonce before accessing file
		if (
			! isset($_POST['add_student_nonce']) ||
			! wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['add_student_nonce'])), 'add_student_action')
		) {
			wp_die(esc_html__('Security check failed.', 'result-management-system-for-institutions'));
		}
	
		if (! empty($_FILES['file']['name'])) {
			if (
				isset($_FILES['file']) &&
				isset($_FILES['file']['tmp_name']) &&
				is_uploaded_file($_FILES['file']['tmp_name'])
			) {
				$imported_file = fopen($_FILES['file']['tmp_name'], 'r');
			} else {
				// Handle file upload error
				wp_safe_redirect(admin_url('admin.php?page=astgdrmsys-add-record&csv_error=upload'));
				exit;
			}
			
			// Get the global custom field labels to use as fallbacks for CSV-imported names.
			$default_labels = get_option('astgdrmsys_custom_field_labels', []);

			// Read and discard the header row.
			$header_row = fgetcsv($imported_file);
			if ($header_row === false) {
				// Handle empty or invalid CSV file
				fclose($imported_file);
				wp_safe_redirect(admin_url('admin.php?page=astgdrmsys-add-record&csv_error=empty'));
				exit;
			}

			// Process each data row in the CSV file
			while ($data = fgetcsv($imported_file)) {
				$this->processCSVRow($data, $default_labels);
			}
	
			fclose($imported_file);
	
			// Redirect to the student record page with a success message
			wp_safe_redirect(admin_url('admin.php?page=astgdrmsys-all-students&csv=imported'));
			exit;
		}
	}
	
	/**
	 * Processes a single row of CSV data.
	 *
	 * @param array $data The CSV row data to be processed.
	 *
	 * @return void
	*/
	private function processCSVRow($data, array $default_labels)
	{
		global $wpdb;
	
		// Fixed student info
		$snocsv        = sanitize_text_field($data[0]);
		$regnocsv      = sanitize_text_field($data[1]);
		$namecsv       = sanitize_text_field($data[2]);
		$gendercsv     = sanitize_text_field($data[3]);
		$fnamecsv      = sanitize_text_field($data[4]);
		$mnamecsv      = sanitize_text_field($data[5]);
		$remarkcsv     = sanitize_text_field($data[6]);
		$classid       = sanitize_text_field($data[7]);
		$department_id = sanitize_text_field($data[8]);
		$section_id    = sanitize_text_field($data[9]);
		$exam_name_id  = sanitize_text_field($data[10]);
		$exam_year_id  = sanitize_text_field($data[11]);
		$is_absent     = isset($data[12]) ? intval($data[12]) : 0;
		if ($is_absent && empty($remarkcsv)) {
			$remarkcsv = 'ABSENT';
		}
	
		$student_image       = sanitize_text_field($data[13] ?? '');
		$fourth_subject_code = sanitize_text_field($data[14] ?? '');
		$not_taken_raw       = sanitize_text_field($data[15] ?? '');
	
		if (empty($namecsv)) {
			return; // skip invalid row
		}
	
		// Process custom fields
		$custom_fields_csv = [];
		$custom_field_start_index = 16;
		$num_custom_fields = count($default_labels);
	
		for ($i = 0; $i < $num_custom_fields; $i++) {
			$name_col_index  = $custom_field_start_index + (2 * $i);
			$value_col_index = $name_col_index + 1;
	
			$value = isset($data[$value_col_index]) ? sanitize_text_field($data[$value_col_index]) : '';
			if ($value === '') {
				continue;
			}
	
			$name = isset($data[$name_col_index]) && $data[$name_col_index] !== ''
				? sanitize_text_field($data[$name_col_index])
				: ($default_labels[$i] ?? '');
	
			if ($name !== '') {
				$custom_fields_csv[] = ['name' => $name, 'value' => $value];
			}
		}
	
		$custom_fields_json = wp_json_encode($custom_fields_csv);
	
		$marks_start_index = $custom_field_start_index + ($num_custom_fields * 2);
		$exam_table = esc_sql($this->prefix . 'astgdrmsys_exam_name');
		$exam_type  = $wpdb->get_var($wpdb->prepare("SELECT exam_type FROM $exam_table WHERE id = %d", $exam_name_id));
	
		$marks_array = [];
		$marks_end_index = count($data);
	
		// Parse Marks
		if ($exam_type === 'triple') {
			for ($i = $marks_start_index; $i + 3 < $marks_end_index; $i += 4) {
				$subject_id = sanitize_text_field($data[$i]);
				if (empty($subject_id)) continue;
	
				$practical_mark = intval($data[$i + 1]);
				$class_mark     = intval($data[$i + 2]);
				$final_mark     = intval($data[$i + 3]);
	
				$marks_array[$subject_id] = [
					'practical' => $practical_mark,
					'class'     => $class_mark,
					'final'     => $final_mark,
					'total'     => $practical_mark + $class_mark + $final_mark,
				];
			}
		} elseif ($exam_type === 'composite') {
			for ($i = $marks_start_index; $i + 2 < $marks_end_index; $i += 3) {
				$subject_id = sanitize_text_field($data[$i]);
				if (empty($subject_id)) continue;
	
				$class_mark = intval($data[$i + 1]);
				$final_mark = intval($data[$i + 2]);
	
				$marks_array[$subject_id] = [
					'class' => $class_mark,
					'final' => $final_mark,
					'total' => $class_mark + $final_mark,
				];
			}
		} else {
			for ($i = $marks_start_index; $i + 1 < $marks_end_index; $i += 2) {
				$subject_id = sanitize_text_field($data[$i]);
				if (empty($subject_id)) continue;
	
				$final_mark = intval($data[$i + 1]);
				$marks_array[$subject_id] = [
					'final' => $final_mark,
					'total' => $final_mark,
				];
			}
		}
	
		// Save the fourth subject
		if (!empty($fourth_subject_code)) {
			$marks_array['fourth_subject'] = $fourth_subject_code;
		}
	
		// Handle NOT TAKEN Subjects
		if (!empty($not_taken_raw)) {
			$not_taken_subjects = array_filter(array_map('trim', explode(',', $not_taken_raw)));
	
			foreach ($not_taken_subjects as $subcode) {
				if (!isset($marks_array[$subcode])) {
					$marks_array[$subcode] = [
						'practical' => 0,
						'class'     => 0,
						'final'     => 0,
						'total'     => 0,
						'not_taken' => 1,
					];
				} else {
					$marks_array[$subcode]['not_taken'] = 1;
					$marks_array[$subcode]['practical'] = 0;
					$marks_array[$subcode]['class']     = 0;
					$marks_array[$subcode]['final']     = 0;
					$marks_array[$subcode]['total']     = 0;
				}
			}
		}
	
		// Insert Student Record
		if (!empty($marks_array)) {
			$student_links = $this->createOrUpdateStudentAndEnrollment([
				'sno'           => $snocsv,
				'regno'         => $regnocsv,
				'name'          => $namecsv,
				'fname'         => $fnamecsv,
				'mname'         => $mnamecsv,
				'gender'        => $gendercsv,
				'class'         => $classid,
				'department'    => $department_id,
				'section'       => $section_id,
				'exam_year'     => $exam_year_id,
				'student_image' => $student_image,
				'custom_fields' => $custom_fields_json,
			]);

			$this->wpdb->insert(
				$this->prefix . 'astgdrmsys_student_result',
				[
					'sid'           => null,
					'student_id'    => $student_links['student_id'],
					'enrollment_id' => $student_links['enrollment_id'],
					'sno'           => $snocsv,
					'regno'         => $regnocsv,
					'name'          => $namecsv,
					'fname'         => $fnamecsv,
					'mname'         => $mnamecsv,
					'gender'        => $gendercsv,
					'remark'        => $remarkcsv,
					'class'         => $classid,
					'department'    => $department_id,
					'section'       => $section_id,
					'exam_name'     => $exam_name_id,
					'exam_year'     => $exam_year_id,
					'is_absent'     => $is_absent,
					'student_image' => $student_image,
					'custom_fields' => $custom_fields_json,
				]
			);
	
			$tobesid = $this->wpdb->insert_id;
	
			$this->wpdb->insert(
				$this->prefix . 'astgdrmsys_mark',
				['sid' => $tobesid, 'marks' => serialize($marks_array)]
			);
		}
	}

	/**
	 * Adds student database references to a result snapshot row.
	 *
	 * @param array<string, mixed> $data Student result data.
	 * @return array<string, mixed>
	 */
	private function attachStudentDatabaseLinks(array $data): array
	{
		$links = $this->createOrUpdateStudentAndEnrollment($data);
		$data['student_id']    = $links['student_id'];
		$data['enrollment_id'] = $links['enrollment_id'];

		return $data;
	}

	/**
	 * Creates or updates a master student and active enrollment from result data.
	 *
	 * @param array<string, mixed> $data Student data.
	 * @return array{student_id:int,enrollment_id:int}
	 */
	private function createOrUpdateStudentAndEnrollment(array $data): array
	{
		$students_table    = $this->prefix . 'astgdrmsys_students';
		$enrollments_table = $this->prefix . 'astgdrmsys_student_enrollments';
		$regno             = isset($data['regno']) ? trim((string) $data['regno']) : '';
		$name              = isset($data['name']) ? trim((string) $data['name']) : '';
		$fname             = isset($data['fname']) ? trim((string) $data['fname']) : '';
		$mname             = isset($data['mname']) ? trim((string) $data['mname']) : '';
		$student_id        = 0;

		if ($regno !== '') {
			$student_id = (int) $this->wpdb->get_var(
				$this->wpdb->prepare("SELECT id FROM {$students_table} WHERE regno = %s ORDER BY id ASC LIMIT 1", $regno)
			);
		}

		if ($student_id <= 0 && $name !== '') {
			$student_id = (int) $this->wpdb->get_var(
				$this->wpdb->prepare(
					"SELECT id FROM {$students_table} WHERE name = %s AND fname = %s AND mname = %s ORDER BY id ASC LIMIT 1",
					$name,
					$fname,
					$mname
				)
			);
		}

		$student_data = [
			'regno'         => $regno !== '' ? $regno : null,
			'name'          => $name,
			'gender'        => isset($data['gender']) ? sanitize_text_field((string) $data['gender']) : '',
			'fname'         => $fname,
			'mname'         => $mname,
			'student_image' => ! empty($data['student_image']) ? esc_url_raw((string) $data['student_image']) : null,
			'custom_fields' => isset($data['custom_fields']) ? (string) $data['custom_fields'] : null,
			'status'        => 'active',
			'updated_at'    => current_time('mysql'),
		];

		if ($student_id > 0) {
			$this->wpdb->update($students_table, $student_data, ['id' => $student_id]);
		} elseif ($name !== '') {
			$student_data['student_uid'] = $this->generateStudentUid();
			$student_data['created_at']  = current_time('mysql');
			$this->wpdb->insert($students_table, $student_data);
			$student_id = (int) $this->wpdb->insert_id;
		}

		$enrollment_id = 0;
		$exam_year_id  = isset($data['exam_year']) ? (int) $data['exam_year'] : 0;
		$class_id      = isset($data['class']) ? (int) $data['class'] : 0;
		$department_id = isset($data['department']) ? (int) $data['department'] : 0;
		$section_id    = isset($data['section']) ? (int) $data['section'] : 0;
		$roll_no       = isset($data['sno']) ? sanitize_text_field((string) $data['sno']) : '';

		if ($student_id > 0 && $exam_year_id > 0 && $class_id > 0 && $department_id > 0) {
			$enrollment_id = (int) $this->wpdb->get_var(
				$this->wpdb->prepare(
					"SELECT id FROM {$enrollments_table} WHERE student_id = %d AND exam_year_id = %d LIMIT 1",
					$student_id,
					$exam_year_id
				)
			);

			$enrollment_data = [
				'student_id'    => $student_id,
				'exam_year_id'  => $exam_year_id,
				'class_id'      => $class_id,
				'department_id' => $department_id,
				'section_id'    => $section_id,
				'roll_no'       => $roll_no,
				'status'        => 'active',
				'updated_at'    => current_time('mysql'),
			];

			if ($enrollment_id > 0) {
				$this->wpdb->update($enrollments_table, $enrollment_data, ['id' => $enrollment_id]);
			} else {
				$enrollment_data['created_at'] = current_time('mysql');
				$this->wpdb->insert($enrollments_table, $enrollment_data);
				$enrollment_id = (int) $this->wpdb->insert_id;
			}
		}

		return [
			'student_id'    => $student_id,
			'enrollment_id' => $enrollment_id,
		];
	}

	/**
	 * Generates a unique master student UID.
	 */
	private function generateStudentUid(): string
	{
		do {
			$uid = 'STD-' . strtoupper(wp_generate_password(12, false, false));
			$exists = (int) $this->wpdb->get_var(
				$this->wpdb->prepare("SELECT COUNT(*) FROM {$this->prefix}astgdrmsys_students WHERE student_uid = %s", $uid)
			);
		} while ($exists > 0);

		return $uid;
	}

}
/**
 * This script initializes the ASTGDRMSYS_StudentRecordManager and calls its display method.
 *
 * @package ResultManagementSystem
 *
 * @var ASTGDRMSYS_StudentRecordManager $ASTGDRMSYS_StudentRecordManager An instance of the ASTGDRMSYS_StudentRecordManager class.
 *
 * @method void astgdrmsys_display() Displays the student record management interface.
 */
$ASTGDRMSYS_StudentRecordManager = new ASTGDRMSYS_StudentRecordManager();
$ASTGDRMSYS_StudentRecordManager->astgdrmsys_display();
?>
