<?php

declare(strict_types=1);
/**
 * Result Management System for Institutions
 *
 * @package           ResultManagementSystem
 * @author            ASTGD
 * @copyright         2025 ASTGD
 * @license           GPL v2 or later
 *
 * @wordpress-plugin
 * Plugin Name:       Result Management System for Institutions
 * Description:       A complete result management system designed for schools and educational institutions. Easily organize student records, generate marksheets, and streamline result publication with a user-friendly interface.
 * Version:           2.0.0
 * Requires at least: 6.2
 * Requires PHP:      7.4
 * Author:            ASTGD
 * Author URI:        https://astgd.com/
 * Text Domain:       result-management-system-for-institutions
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 */

namespace ASTGDRMSYS\ResultManagement;

ob_start();

// Exit if accessed directly
if (! defined('ABSPATH')) {
	exit;
}

// Plugin constants
define('ASTGDRMSYS_VERSION', '2.0.0');
define('ASTGDRMSYS_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('ASTGDRMSYS_PLUGIN_URL', plugin_dir_url(__FILE__));
define('ASTGDRMSYS_PLUGIN_BASENAME', plugin_basename(__FILE__));

//Define Encryption Key
if (!defined('ASTGDRMSYS_SECRET_KEY')) {
	define('ASTGDRMSYS_SECRET_KEY', '5f7b1a9273c4d8e0f2a6c3e89b4d2f17'); // Must be 32 chars for AES-256
}
if (!defined('ASTGDRMSYS_SECRET_IV')) {
	define('ASTGDRMSYS_SECRET_IV', '9a7b4c2e1f6d8a0b'); // Must be 16 chars
}
if (!defined('ASTGDRMSYS_ENCRYPT_METHOD')) {
	define('ASTGDRMSYS_ENCRYPT_METHOD', 'AES-256-CBC');
}
/**
 * Hook into the 'admin_init' action to execute a custom function.
 *
 * This function will be executed during the WordPress admin initialization process.
 */

/**
 * Checks if all necessary dependencies are met.
 *
 * This function verifies whether all required dependencies for the plugin
 * are available and properly configured.
 *
 * @return bool Returns true if all dependencies are met, false otherwise.
 */
function astgdrmsys_check_dependencies(): bool
{
	$requirements_met = true;

	// Check PHP version
	if (version_compare(PHP_VERSION, '7.4', '<')) {
		add_action(
			'admin_notices',
			function () {
				echo '<div class="error"><p>' .
					esc_html(
						sprintf(
							// Translators: %s represents the current PHP version.
							__('Result Management System for Institutions requires PHP 7.4 or higher. Current version is %s', 'result-management-system-for-institutions'),
							PHP_VERSION
						)
					) .

					'</p></div>';
			}
		);
		$requirements_met = false;
	}

	// Check WordPress version
	if (version_compare($GLOBALS['wp_version'], '5.8', '<')) {
		add_action(
			'admin_notices',
			function () {
				echo '<div class="error"><p>' .
					esc_html(
						__('Result Management System for Institutions requires WordPress 5.8 or higher.', 'result-management-system-for-institutions') .
							'</p></div>'
					);
			}
		);
		$requirements_met = false;
	}

	// Check if required PHP extensions are loaded
	$required_extensions = array('mysqli', 'mbstring');
	$missing_extensions  = array_filter(
		$required_extensions,
		function ($ext) {
			return ! extension_loaded($ext);
		}
	);

	if (! empty($missing_extensions)) {
		add_action(
			'admin_notices',
			function () use ($missing_extensions) {
				echo '<div class="error"><p>' .
					esc_html(
						sprintf(
							// Translators: %s is a list of required PHP extensions.
							__('Result Management System for Institutions requires the following PHP extensions: %s', 'result-management-system-for-institutions'),
							implode(', ', $missing_extensions)
						)
					) .
					'</p></div>';
			}
		);
		$requirements_met = false;
	}

	// Check write permissions for upload directory
	$upload_dir = wp_upload_dir();
	if (! wp_is_writable($upload_dir['basedir'])) {
		add_action(
			'admin_notices',
			function () {
				echo '<div class="error"><p>' .
					esc_html(
						__('Result Management System for Institutions requires write permissions for the uploads directory.', 'result-management-system-for-institutions') .
							'</p></div>'
					);
			}
		);
		$requirements_met = false;
	}

	return $requirements_met;
}

// Checking for dependencies
if (! astgdrmsys_check_dependencies()) {
	return;
}

/**
 * Adds plugin's menu and submenus to the WordPress admin menu.
 *
 * This function is responsible for adding a new item to the WordPress admin menu.
 * It should be hooked to the appropriate WordPress action to ensure it is executed
 * at the right time.
 *
 * @return void
 */

function astgdrmsys_admin_menu(): void
{
        add_menu_page(
                __('Student Result Management', 'result-management-system-for-institutions'),
                __('Student Result Management', 'result-management-system-for-institutions'),
                'access_astgdrmsys_plugin',
                'astgdrmsys-student-result',
                'ASTGDRMSYS\ResultManagement\astgdrmsys_plugin_page',
                'dashicons-welcome-learn-more',
                25
        );

        $submenu_pages = array(
                array('astgdrmsys-student-result', __('Dashboard', 'result-management-system-for-institutions'), __('Dashboard', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-student-result', 'ASTGDRMSYS\ResultManagement\astgdrmsys_plugin_page'),
                array('astgdrmsys-student-result', __('Class Management', 'result-management-system-for-institutions'), __('All Classes', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-class', 'ASTGDRMSYS\ResultManagement\astgdrmsys_add_class'),
                array('astgdrmsys-student-result', __('Department Management', 'result-management-system-for-institutions'), __('All Departments', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-department', 'ASTGDRMSYS\ResultManagement\astgdrmsys_add_department'),
                array('astgdrmsys-student-result', __('Section Management', 'result-management-system-for-institutions'), __('All Sections', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-section', 'ASTGDRMSYS\ResultManagement\astgdrmsys_add_section'),
                
			    array('astgdrmsys-student-result', __('Subject Management', 'result-management-system-for-institutions'), __('All Subject', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-subject', 'ASTGDRMSYS\ResultManagement\astgdrmsys_add_subject'),
                array('astgdrmsys-student-result', __('Student Database', 'result-management-system-for-institutions'), __('Student Database', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-student-database', 'ASTGDRMSYS\ResultManagement\astgdrmsys_student_database'), 
			     array('astgdrmsys-student-result', __('Exam Year Management', 'result-management-system-for-institutions'), __('Exam Year', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-exam-year', 'ASTGDRMSYS\ResultManagement\astgdrmsys_add_exam_year'),
                array('astgdrmsys-student-result', __('Exam Name Management', 'result-management-system-for-institutions'), __('Exam List', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-exam-name', 'ASTGDRMSYS\ResultManagement\astgdrmsys_add_exam_name'),
                
                // array('astgdrmsys-student-result', __('Add Student Result', 'result-management-system-for-institutions'), __('Add Student To Exam', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-add-record', 'ASTGDRMSYS\ResultManagement\astgdrmsys_add_record'),
                array('astgdrmsys-student-result', __('Add/Edit Mark', 'result-management-system-for-institutions'), __('Add / Update Mark', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-add-mark', 'ASTGDRMSYS\ResultManagement\astgdrmsys_add_mark'),
                array('astgdrmsys-student-result', __('Generate CSV for Bulk Upload', 'result-management-system-for-institutions'), __('Generate CSV', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-generate-bulk-csv', 'ASTGDRMSYS\ResultManagement\astgdrmsys_generate_bulk_csv'),
                array('astgdrmsys-student-result', __('Exam Result Records', 'result-management-system-for-institutions'), __('Exam Result Records', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-all-students', 'ASTGDRMSYS\ResultManagement\astgdrmsys_all_students'),
                array('astgdrmsys-student-result', __('Download Student Marksheet', 'result-management-system-for-institutions'), __('Download Marksheet', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-download-marksheet', 'ASTGDRMSYS\ResultManagement\astgdrmsys_download_marksheet'),
                array('astgdrmsys-student-result', __('Configure & Settings', 'result-management-system-for-institutions'), __('Settings', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-settings', 'ASTGDRMSYS\ResultManagement\astgdrmsys_settings'),
                array('astgdrmsys-student-result', __('Help & Guide', 'result-management-system-for-institutions'), __('Help & Guide', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-help', 'ASTGDRMSYS\ResultManagement\astgdrmsys_help'),
                array('astgdrmsys-student-result', __('Shortcode Generator', 'result-management-system-for-institutions'), __('Shortcode Generator', 'result-management-system-for-institutions'), 'manage_options', 'astgdrmsys-shortcode-generator', 'ASTGDRMSYS\ResultManagement\astgdrmsys_shortcode_generator'),
                array('v', __('View', 'result-management-system-for-institutions'), __('View', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-viewrec', 'ASTGDRMSYS\ResultManagement\astgdrmsys_viewrec'),
                array('d', __('Delete', 'result-management-system-for-institutions'), __('Delete', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-delrec', 'ASTGDRMSYS\ResultManagement\astgdrmsys_delrec'),
                array('f', __('Edit Record', 'result-management-system-for-institutions'), __('Edit Record', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-edit-record', 'ASTGDRMSYS\ResultManagement\astgdrmsys_edit_record'),
                array('astgdrmsys-student-result', __('User Management', 'result-management-system-for-institutions'), __('User Management', 'result-management-system-for-institutions'), 'manage_options', 'astgdrmsys-user-management', 'ASTGDRMSYS\ResultManagement\astgdrmsys_user_management'),
                array('astgdrmsys-student-result', __('Restore/Backup', 'result-management-system-for-institutions'), __('Restore/Backup', 'result-management-system-for-institutions'), 'manage_options', 'astgdrmsys-backup-restore', 'ASTGDRMSYS\ResultManagement\astgdrmsys_backup_restore'),
        );

        foreach ($submenu_pages as $page) {
                add_submenu_page(...$page);
        }

        add_submenu_page(null, __('Update Marks from CSV', 'result-management-system-for-institutions'), __('Update Mark (CSV)', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-update-marks-csv', 'ASTGDRMSYS\ResultManagement\astgdrmsys_update_marks_csv');
        add_submenu_page(null, __('Insert Result from CSV', 'result-management-system-for-institutions'), __('Insert Result', 'result-management-system-for-institutions'), 'access_astgdrmsys_plugin', 'astgdrmsys-insert-result', 'ASTGDRMSYS\ResultManagement\astgdrmsys_insert_result');
}
add_action('admin_menu', 'ASTGDRMSYS\ResultManagement\astgdrmsys_admin_menu');

// Registering custom capabilities upon plugin activation
register_activation_hook(__FILE__, 'ASTGDRMSYS\ResultManagement\assign_plugin_capabilities');
add_action('init', 'ASTGDRMSYS\ResultManagement\assign_plugin_capabilities');

function assign_plugin_capabilities()
{
        $roles = ['administrator'];
        $capability = 'access_astgdrmsys_plugin';

	foreach ($roles as $role_name) {
		$role = get_role($role_name);
                if ($role && !$role->has_cap($capability)) {
                        $role->add_cap($capability);
                }
        }
}
assign_plugin_capabilities();

/**
 * Adds a new record to the rms (Result Management System for Institutions) system.
 *
 * This function is responsible for adding a new record to the database or
 * performing any necessary operations to store the record within the rms system.
 *
 * @return void
 */
function astgdrmsys_add_record(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/student-record/add-record.php';
}

/**
 * Displays the reusable student database management page.
 *
 * @return void
 */
function astgdrmsys_student_database(): void
{
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/student-database/student-database.php';
}

/**
 * Adds a mark to the system.
 *
 * This function is responsible for adding a mark to the system.
 * It does not take any parameters and does not return any value.
 *
 * @return void
 */
function astgdrmsys_add_mark(): void
{
	// Check if the user has the required capability to access the plugin
	if (! current_user_can('access_astgdrmsys_plugin')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	$active_tab = isset($_GET['mark_tab']) ? sanitize_key(wp_unslash($_GET['mark_tab'])) : 'manual';
	if (isset($_GET['addid'])) {
		$active_tab = 'manual';
	}

	astgdrmsys_render_mark_tabs($active_tab);
	astgdrmsys_render_mark_tab_content($active_tab);
}

/**
 * Renders the Add/Update Mark tab navigation.
 *
 * @param string $active_tab Current tab key.
 * @return void
 */
function astgdrmsys_render_mark_tabs(string $active_tab): void
{
	$tabs = astgdrmsys_get_mark_tabs();

	if (! isset($tabs[$active_tab])) {
		reset($tabs);
		$active_tab = (string) key($tabs);
	}

	echo '<div class="wrap astgdrmsys-mark-tabs-wrap">';
	echo '<h1>' . esc_html__('Add/Update Mark', 'result-management-system-for-institutions') . '</h1>';
	echo '<nav class="nav-tab-wrapper" style="margin-bottom: 20px;">';

	foreach ($tabs as $tab => $label) {
		$url = add_query_arg(
			array(
				'page'     => 'astgdrmsys-add-mark',
				'mark_tab' => $tab,
			),
			admin_url('admin.php')
		);
		$class = $active_tab === $tab ? ' nav-tab-active' : '';
		echo '<a class="nav-tab' . esc_attr($class) . '" href="' . esc_url($url) . '">' . esc_html($label) . '</a>';
	}

	echo '</nav>';
	echo '</div>';
}

/**
 * Returns tabs available to the current user.
 *
 * @return array<string, string>
 */
function astgdrmsys_get_mark_tabs(): array
{
	$tabs = array();

	if (current_user_can('manage_options')) {
		$tabs['manual']     = __('Add / Update Mark', 'result-management-system-for-institutions');
		$tabs['retake']     = __('Retake Marks', 'result-management-system-for-institutions');
		$tabs['csv_update'] = __('Update Mark (CSV)', 'result-management-system-for-institutions');
	}

	$tabs['insert_result'] = __('Insert Result', 'result-management-system-for-institutions');

	return $tabs;
}

/**
 * Loads the selected Add/Update Mark tab content.
 *
 * @param string $active_tab Current tab key.
 * @return void
 */
function astgdrmsys_render_mark_tab_content(string $active_tab): void
{
	if ('csv_update' === $active_tab) {
		if (! current_user_can('manage_options')) {
			wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
		}

		include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/update-marks-csv/csv-update.php';
		return;
	}

	if ('retake' === $active_tab) {
		if (! current_user_can('manage_options')) {
			wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
		}

		include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/mark/retake-mark.php';
		return;
	}

	if ('insert_result' === $active_tab) {
		include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/insert-result/insert-result.php';
		return;
	}

	if (! current_user_can('manage_options')) {
		astgdrmsys_render_mark_tab_content('insert_result');
		return;
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/mark/add-mark.php';
}

/**
 * Updates marks from a CSV file.
 *
 * This function reads a CSV file and updates the marks accordingly.
 *
 * @return void
 */
function astgdrmsys_update_marks_csv(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	astgdrmsys_render_mark_tabs('csv_update');
	astgdrmsys_render_mark_tab_content('csv_update');
}


/**
 * Generates a CSV template for bulk upload.
 *
 * @return void
 */
function astgdrmsys_generate_bulk_csv(): void
{
	if (! current_user_can('access_astgdrmsys_plugin')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/generate-bulk-csv/generate-bulk-csv.php';
}

/**
 * Inserts result from a CSV file.
 *
 * This function includes the PHP file responsible for inserting results from a CSV file.
 * The file is located in the 'menu-files/insert-result/' directory within the plugin directory.
 *
 * @return void
 */
function astgdrmsys_insert_result(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('access_astgdrmsys_plugin')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	astgdrmsys_render_mark_tabs('insert_result');
	astgdrmsys_render_mark_tab_content('insert_result');
}

/**
 * Displays the rms plugin page.
 *
 * This function is responsible for rendering the main Dashboard page of the rms plugin.
 *
 * @return void
 */
function astgdrmsys_plugin_page(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/dashboard.php';
}

/**
 * Renders the Pro-only notice for user management.
 */
function astgdrmsys_user_management(): void
{
        if (! current_user_can('manage_options')) {
                wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
        }

        echo '<div class="wrap astgdrmsys-user-management astgdrmsys-pro-notice">';
        echo '<h1>' . esc_html__('User Management is available in Pro only', 'result-management-system-for-institutions') . '</h1>';
        echo '<p>' . esc_html__('The free version does not include user management. Upgrade to Pro to create teacher and student logins for controlled result access.', 'result-management-system-for-institutions') . '</p>';
        echo '<ul style="list-style:disc;margin-left:20px;">';
        echo '<li>' . esc_html__('Teachers can log in and update marks only for their allowed subjects.', 'result-management-system-for-institutions') . '</li>';
        echo '<li>' . esc_html__('Students can log in and check only their own marks.', 'result-management-system-for-institutions') . '</li>';
        echo '<li>' . esc_html__('Premium ticket support is included.', 'result-management-system-for-institutions') . '</li>';
        echo '<li>' . esc_html__('Custom result sheet templates are included.', 'result-management-system-for-institutions') . '</li>';
        echo '<li>' . esc_html__('All future Pro updates are included.', 'result-management-system-for-institutions') . '</li>';
        echo '</ul>';
        echo '<p><a class="button button-primary" href="' . esc_url('https://astgd.com/result-management-system') . '" target="_blank" rel="noopener noreferrer">' . esc_html__('View Pro Version', 'result-management-system-for-institutions') . '</a></p>';
        echo '</div>';
}

/**
 * Provides backup and restore tools for the plugin and database.
 */
function astgdrmsys_backup_restore(): void
{
        if (! current_user_can('manage_options')) {
                wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
        }

        include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/backup-restore/backup-restore.php';
}

/**
 * Retrieves all students.
 *
 * This function fetches and returns a list of all students.
 *
 * @return void
 */
function astgdrmsys_all_students(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/all-students/all-students.php';
}

/**
 * Adds a class to the rms (Result Management System for Institutions) plugin.
 *
 * This function is responsible for adding a specific class to the rms plugin.
 *
 * @return void
 */
function astgdrmsys_add_class(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}
	// Include the class file
	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/class/add-class.php';
}

/**
 * Adds a new department to the system.
 *
 * This function is responsible for adding a new department to the system.
 * It performs necessary validations and inserts the department data into the database.
 *
 * @return void
 */
function astgdrmsys_add_department(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}
	// Include the department file
	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/department/add-department.php';
}

/**
 * Adds a new section to the result management plugin.
 *
 * This function is responsible for adding a new section to the Result Management System for Institutions plugin.
 *
 * @return void
 */
function astgdrmsys_add_section(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}
	// Include the section file
	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/section/add-section.php';
}

/**
 * Adds a new exam name to the system.
 *
 * This function is responsible for adding a new exam name to the result management system.
 *
 * @return void
 */
function astgdrmsys_add_exam_name(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/exam-name/add-exam-name.php';
}

/**
 * Adds a new exam year to the system.
 *
 * This function is responsible for adding a new exam year to the result management system.
 *
 * @return void
 */
function astgdrmsys_add_exam_year(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/exam-year/add-exam-year.php';
}

/**
 * Adds a subject to the system.
 *
 * This function is responsible for adding a new subject to the system.
 *
 * @return void
 */
function astgdrmsys_add_subject(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}
	// Include the subject file
	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/subject/add-subject.php';
}

/**
 * Provides help or information related to the rms (Result Management System for Institutions) plugin.
 *
 * This function is intended to assist users by providing necessary help or information
 * about the functionalities and usage of the rms plugin.
 *
 * @return void
 */
function astgdrmsys_help(): void
{
        $nonce_action = 'astgdrmsys_help_nonce';

	$nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : '';

	if (! wp_verify_nonce($nonce, $nonce_action)) {
		// First-time load: generate and redirect with nonce
		$url = add_query_arg('_wpnonce', wp_create_nonce($nonce_action), isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '');
		wp_safe_redirect($url);
		exit;
	}

        // Nonce is valid now — render help page
        include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/help/help.php';
}

/**
 * Displays the shortcode generator page.
 */
function astgdrmsys_shortcode_generator(): void
{
        if (! current_user_can('manage_options')) {
                wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
        }

        include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/shortcode/shortcode-generator.php';
}
/**
 * Displays the rms view record.
 *
 * This function is responsible for rendering the view record in the rms plugin.
 *
 * @return void
 */
function astgdrmsys_viewrec(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/view/view.php';
}

/**
 * Edits a record in the Result Management System for Institutions plugin.
 *
 * This function is responsible for handling the editing of records within the
 * Result Management System for Institutions plugin. It performs necessary operations to update
 * the record based on the provided data.
 *
 * @return void
 */
function astgdrmsys_edit_record(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/edit-record/edit-record.php';
}

/**
 * Deletes a record in the rms (Result Management System for Institutions) system.
 *
 * This function is responsible for deleting a specific record from the database
 * or any other storage mechanism used by the rms plugin.
 *
 * @return void
 */
function astgdrmsys_delrec(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}

	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/delete.php';
}

/**
 * Displays the published results in the rms (Result Management System for Institutions) plugin.
 *
 * This function is responsible for rendering the published results page in the rms plugin.
 *
 * @return void
 */
function astgdrmsys_published_results(): void
{
	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/published-results/published-results.php';
}

/**
 * Initializes the settings for the rms (Result Management System for Institutions) plugin.
 *
 * This function sets up the necessary configurations and options for the plugin.
 *
 * @return void
 */
function astgdrmsys_download_marksheet(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}
	// Include the download marksheet file
	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/marksheet/download-marksheet.php';
}

/**
 * Initializes the settings for the rms (Result Management System for Institutions) plugin.
 *
 * This function sets up the necessary configurations and options for the plugin.
 *
 * @return void
 */
function astgdrmsys_settings(): void
{
	// Check if the user has the required capability to manage options
	if (! current_user_can('manage_options')) {
		wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'result-management-system-for-institutions'));
	}
	// Include the settings file
	include ASTGDRMSYS_PLUGIN_DIR . 'menu-files/settings/settings.php';
}

function astgdrmsys_admin_styles(): void
{
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended
	if (! isset($_GET['page'])) {
		return;
	}
	// phpcs:ignore WordPress.Security.NonceVerification.Recommended
	$page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';

        $common_pages = array(
                'astgdrmsys-student-result',
                'astgdrmsys-student-database',
                'astgdrmsys-subject',
                'astgdrmsys-department',
                'astgdrmsys-section',
                'astgdrmsys-exam-name',
                'astgdrmsys-exam-year',
                'astgdrmsys-class',
                'astgdrmsys-add-record',
                'astgdrmsys-add-mark',
                'astgdrmsys-insert-result',
                'astgdrmsys-user-management',
                'astgdrmsys-all-students',
                'astgdrmsys-published-results',
                'astgdrmsys-download-marksheet',
                'astgdrmsys-settings',
                'astgdrmsys-help',
                'astgdrmsys-viewrec',
                'astgdrmsys-edit-record',
                'astgdrmsys-update-marks-csv',
                'astgdrmsys-generate-bulk-csv',
                'astgdrmsys-shortcode-generator',
                'astgdrmsys-backup-restore',
        );

	if (in_array($page, $common_pages, true)) {
		wp_enqueue_style(
			'astgdrmsys-bootstrap',
			ASTGDRMSYS_PLUGIN_URL . 'css/bootstrap.css',
			array(),
			ASTGDRMSYS_VERSION
		);

		wp_enqueue_style(
			'astgdrmsys-w3schools',
			ASTGDRMSYS_PLUGIN_URL . 'css/w3.css',
			array(),
			ASTGDRMSYS_VERSION
		);

		wp_enqueue_style(
			'astgdrmsys-admin-common',
			ASTGDRMSYS_PLUGIN_URL . 'css/admin-style.css',
			array(),
			ASTGDRMSYS_VERSION
		);
	}

	$page_styles = array(
		'astgdrmsys-student-result'   => 'css/dashboard.css',
		'astgdrmsys-subject'          => 'menu-files/subject/subject-style.css',
		'astgdrmsys-department'       => 'menu-files/class/style.css',
		'astgdrmsys-section'          => 'menu-files/class/style.css',
		'astgdrmsys-exam-name'        => 'menu-files/exam-name/exam-name-style.css',
		'astgdrmsys-exam-year'        => 'menu-files/class/style.css',
		'astgdrmsys-class'            => 'menu-files/class/style.css',
		'astgdrmsys-add-record'       => 'menu-files/student-record/record-style.css',
		'astgdrmsys-add-mark'         => 'menu-files/mark/mark-style.css',
		'astgdrmsys-insert-result'    => 'menu-files/insert-result/insert-result-style.css',
                'astgdrmsys-all-students'     => 'menu-files/all-students/all-student-style.css',
		'astgdrmsys-published-results' => 'menu-files/published-results/published-results-style.css',
		'astgdrmsys-download-marksheet' => 'menu-files/mark/mark-style.css',
		'astgdrmsys-settings'         => 'menu-files/settings/style.css',
		'astgdrmsys-viewrec'          => 'menu-files/show-result/style.css',
		'astgdrmsys-edit-record'      => 'menu-files/edit-record/editrec-style.css',
		'astgdrmsys-update-marks-csv' => 'menu-files/update-marks-csv/update-marks-style.css',
		'astgdrmsys-generate-bulk-csv' => 'menu-files/update-marks-csv/update-marks-style.css',
		'astgdrmsys-help'             => 'menu-files/help/style.css',
	);

	if (isset($page_styles[$page])) {
		wp_enqueue_style(
			"astgdrmsys-{$page}-style",
			ASTGDRMSYS_PLUGIN_URL . $page_styles[$page],
			array(),
			ASTGDRMSYS_VERSION
		);
	}

	if ('astgdrmsys-add-mark' === $page) {
		wp_enqueue_style(
			'astgdrmsys-update-marks-csv-style',
			ASTGDRMSYS_PLUGIN_URL . 'menu-files/update-marks-csv/update-marks-style.css',
			array(),
			ASTGDRMSYS_VERSION
		);

		wp_enqueue_style(
			'astgdrmsys-insert-result-style',
			ASTGDRMSYS_PLUGIN_URL . 'menu-files/insert-result/insert-result-style.css',
			array(),
			ASTGDRMSYS_VERSION
		);
	}

	if (in_array($page, $common_pages, true)) {
		wp_enqueue_style(
			'astgdrmsys-admin-modern',
			ASTGDRMSYS_PLUGIN_URL . 'css/admin-modern.css',
			array('astgdrmsys-admin-common'),
			ASTGDRMSYS_VERSION
		);
	}

}
add_action('admin_enqueue_scripts', 'ASTGDRMSYS\ResultManagement\astgdrmsys_admin_styles');

/**
 * Adds custom styles for the help page in the admin area.
 *
 * This function adds custom CSS styles to the admin area of the WordPress site,
 * specifically for the help page of the Result Management System for Institutions plugin.
 *
 * @return void
 */

/**
 * Enqueues the frontend styles for the plugin.
 *
 * This function is responsible for adding the necessary CSS stylesheets
 * to the frontend of the WordPress site when the plugin is active.
 *
 * @return void
 */
function astgdrmsys_frontend_styles(): void
{
	wp_enqueue_style(
		'astgdrmsys-show-result-css',
		ASTGDRMSYS_PLUGIN_URL . 'menu-files/show-result/style.css',
		array(),
		ASTGDRMSYS_VERSION
	);

	wp_enqueue_style(
		'astgdrmsys-show-result-bootstrap',
		ASTGDRMSYS_PLUGIN_URL . 'css/bootstrap.css',
		array(),
		ASTGDRMSYS_VERSION
	);
}
add_action('wp_enqueue_scripts', 'ASTGDRMSYS\ResultManagement\astgdrmsys_frontend_styles');

/**
 * Removes the footer from the WordPress admin dashboard.
 *
 * @return string The modified footer text.
 */
function astgdrmsys_remove_admin_footer(): string
{
	return '';
}
add_filter('admin_footer_text', 'ASTGDRMSYS\ResultManagement\astgdrmsys_remove_admin_footer');
add_filter('update_footer', 'ASTGDRMSYS\ResultManagement\astgdrmsys_remove_admin_footer', 9999);

/**
 * Enqueues custom scripts for the plugin.
 *
 * This function is responsible for adding the necessary JavaScript files
 * to the WordPress admin area and frontend when the plugin is active.
 *
 * @return void
 */
function astgdrmsys_custom_scripts(): void
{
	if (is_admin()) {
		$page = isset($_GET['page']) ? sanitize_key(wp_unslash($_GET['page'])) : '';
		if ('' === $page || strpos($page, 'astgdrmsys-') !== 0) {
			return;
		}
	}

	// Libraries
	wp_enqueue_script(
		'astgdrmsys-html2canvas',
		ASTGDRMSYS_PLUGIN_URL . 'js/html2canvas.min.js',
		array(),
		'1.4.1',
		true
	);

	wp_enqueue_script(
		'astgdrmsys-pdfobject',
		ASTGDRMSYS_PLUGIN_URL . 'js/pdfobject.min.js',
		array(),
		'2.1.1',
		true
	);

	wp_enqueue_script(
		'astgdrmsys-jspdf',
		ASTGDRMSYS_PLUGIN_URL . 'js/jspdf.umd.min.js',
		array('astgdrmsys-pdfobject'),
		'3.0.1',
		true
	);

	// Custom scripts
	wp_enqueue_script(
		'astgdrmsys-csv-update',
		ASTGDRMSYS_PLUGIN_URL . 'js/csv-update.js',
		array('jquery'),
		ASTGDRMSYS_VERSION,
		true
	);

	wp_enqueue_script(
		'astgdrmsys-show-result',
		ASTGDRMSYS_PLUGIN_URL . 'js/show-result.js',
		array('jquery'),
		ASTGDRMSYS_VERSION,
		true
	);

	wp_enqueue_script(
		'astgdrmsys-download-marksheet',
		ASTGDRMSYS_PLUGIN_URL . 'js/download-marksheet.js',
		array('jquery'),
		ASTGDRMSYS_VERSION,
		true
	);

	wp_enqueue_script(
		'astgdrmsys-custom-js',
		ASTGDRMSYS_PLUGIN_URL . 'js/custom.js',
		array('jquery', 'astgdrmsys-jspdf', 'astgdrmsys-html2canvas'),
		ASTGDRMSYS_VERSION,
		true
	);

	// Create nonce and pass it to JavaScript
	wp_localize_script(
		'astgdrmsys-custom-js',
		'astgdrmsys_ajax_object',
		array(
			'ajaxurl'   => admin_url('admin-ajax.php'),
			'nonce'     => wp_create_nonce('astgdrmsys_ajax_nonce'),
			'pluginUrl' => ASTGDRMSYS_PLUGIN_URL, // plugin URL
		)
	);

	$shortcode_atts = array(
		'sclass'      => isset($_GET['sclass']) ? sanitize_text_field(wp_unslash($_GET['sclass'])) : '',
		'sdepartment' => isset($_GET['sdepartment']) ? sanitize_text_field(wp_unslash($_GET['sdepartment'])) : '',
		'ssection'    => isset($_GET['ssection']) ? sanitize_text_field(wp_unslash($_GET['ssection'])) : '',
		's_exam_name' => isset($_GET['s_exam_name']) ? sanitize_text_field(wp_unslash($_GET['s_exam_name'])) : '',
	);

        wp_localize_script(
                'astgdrmsys-show-result',
                'astgdrmsys_result_object',
                array(
                        'shortcode_atts' => $shortcode_atts,
                        'sclass'      => $shortcode_atts['sclass'],
                        'sdepartment' => $shortcode_atts['sdepartment'],
                        'ssection'    => $shortcode_atts['ssection'],
                        's_exam_name' => $shortcode_atts['s_exam_name'],
                )
	);
}
add_action('wp_enqueue_scripts', 'ASTGDRMSYS\ResultManagement\astgdrmsys_custom_scripts');
add_action('admin_enqueue_scripts', 'ASTGDRMSYS\ResultManagement\astgdrmsys_custom_scripts');


/**
 * Handles AJAX requests for the plugin.
 *
 * This function is responsible for handling AJAX requests made to the plugin.
 * It verifies the security token and processes the request accordingly.
 *
 * @return void
 */
function astgdrmsys_verify_ajax_request(): bool
{
	// Check if the request is an AJAX request
	if (! check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce', false)) {
		wp_send_json_error('Invalid security token');
		return false;
	}
	return true;
}

/**
 * Retrieves departments by class.
 *
 * This function fetches and returns a list of departments based on the provided class ID.
 *
 * @return void
 */
function get_departments_by_class(): void
{
	// Verify the AJAX request
	if (! astgdrmsys_verify_ajax_request()) {
		return;
	}
	check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce');

	global $wpdb;
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
	$departments = $wpdb->get_results(
		"SELECT id, department FROM {$wpdb->prefix}astgdrmsys_department ORDER BY department ASC"
	);

	wp_send_json_success($departments ?: array());
}
add_action('wp_ajax_astgdrmsys_get_departments_by_class', 'ASTGDRMSYS\ResultManagement\get_departments_by_class');
add_action('wp_ajax_nopriv_astgdrmsys_get_departments_by_class', 'ASTGDRMSYS\ResultManagement\get_departments_by_class');

/**
 * Retrieves sections by department and, when provided, class.
 *
 * This function fetches and returns a list of sections based on the provided department ID and optional class ID.
 *
 * @return void
 */
function get_sections_by_department(): void
{
	if (! astgdrmsys_verify_ajax_request()) {
		return;
	}
	check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce');

	$department_id = filter_input(INPUT_POST, 'department', FILTER_VALIDATE_INT);
	if (! $department_id) {
		wp_send_json_error('Invalid department ID');
	}
	$class_id = filter_input(INPUT_POST, 'class', FILTER_VALIDATE_INT);

	global $wpdb;
	$where  = array('s.department = %d');
	$params = array($department_id);

	if ($class_id) {
		$where[]  = 'c.id = %d';
		$params[] = $class_id;
	}

	$class_join = $class_id ? " INNER JOIN {$wpdb->prefix}astgdrmsys_class c ON s.classname = c.class" : '';

	// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
	$sections = $wpdb->get_results(
		$wpdb->prepare(
			"SELECT s.id, s.section FROM {$wpdb->prefix}astgdrmsys_section s{$class_join} WHERE " . implode(' AND ', $where) . ' ORDER BY s.section ASC, s.id ASC',
			$params
		)
	);

	wp_send_json_success($sections ?: array());
}
add_action('wp_ajax_astgdrmsys_get_sections_by_department', 'ASTGDRMSYS\ResultManagement\get_sections_by_department');
add_action('wp_ajax_nopriv_astgdrmsys_get_sections_by_department', 'ASTGDRMSYS\ResultManagement\get_sections_by_department');

/**
 * Retrieves subjects by class.
 *
 * This function fetches and returns a list of subjects based on the provided class ID.
 *
 * @return void
 */
function get_exam_names_by_class(): void
{
	if (! astgdrmsys_verify_ajax_request()) {
		return;
	}
	check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce');

	$class_id = filter_input(INPUT_POST, 'class', FILTER_VALIDATE_INT);
	if (! $class_id) {
		wp_send_json_error('Invalid class ID');
	}

	global $wpdb;
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
	$exams = $wpdb->get_results(
		$wpdb->prepare(
			"SELECT MIN(id) AS id, exam_name, exam_year, exam_year_id, COALESCE(exam_category, 'general_exam') AS exam_category
			FROM {$wpdb->prefix}astgdrmsys_exam_name
			WHERE class_id = %d
			GROUP BY exam_name, exam_year, exam_year_id, COALESCE(exam_category, 'general_exam')
			ORDER BY exam_year DESC, exam_name ASC",
			$class_id
		)
	);

	wp_send_json_success($exams ?: array());
}
add_action('wp_ajax_astgdrmsys_get_exam_names_by_class', 'ASTGDRMSYS\ResultManagement\get_exam_names_by_class');
add_action('wp_ajax_nopriv_astgdrmsys_get_exam_names_by_class', 'ASTGDRMSYS\ResultManagement\get_exam_names_by_class');

/**
 * Retrieves exam names by class and department.
 *
 * Provides a filtered list of exams for the given class and optional department.
 *
 * @return void
 */
function get_exam_names_by_class_and_department(): void
{
	if (! astgdrmsys_verify_ajax_request()) {
		return;
	}
	check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce');

	$class_id = filter_input(INPUT_POST, 'class', FILTER_VALIDATE_INT);
	if (! $class_id) {
		wp_send_json_error('Invalid class ID');
	}

	$include_published = filter_input(INPUT_POST, 'include_published', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);

	global $wpdb;

	$exam_table = $wpdb->prefix . 'astgdrmsys_exam_name';

	$where_clauses = array('class_id = %d');
	$query_params   = array($class_id);
	if (! $include_published) {
		$where_clauses[] = '(result_publish_status IS NULL OR result_publish_status = 0)';
	}

	$category_raw = isset($_POST['category']) ? sanitize_text_field(wp_unslash($_POST['category'])) : '';
	if ($category_raw) {
		$categories = array_filter(array_map('trim', explode(',', $category_raw)));
		if (! empty($categories)) {
			$placeholders   = implode(',', array_fill(0, count($categories), '%s'));
			$where_clauses[] = "COALESCE(exam_category, 'general_exam') IN ($placeholders)";
			$query_params    = array_merge($query_params, $categories);
		}
	}

	$sql = sprintf(
		"SELECT id, exam_name, exam_year, exam_year_id, department, COALESCE(exam_category, 'general_exam') AS exam_category FROM %s WHERE %s ORDER BY exam_year DESC, exam_name ASC",
		$exam_table,
		implode(' AND ', $where_clauses)
	);

	// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
	$exams = $wpdb->get_results(
		$wpdb->prepare($sql, $query_params),
		ARRAY_A
	);

	$department_id = filter_input(INPUT_POST, 'department', FILTER_VALIDATE_INT);

	if ($department_id && ! empty($exams)) {
		$department_table = $wpdb->prefix . 'astgdrmsys_department';
		$department_name  = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT department FROM {$department_table} WHERE id = %d",
				$department_id
			)
		);

		if (! empty($department_name)) {
			$filtered = array();

			foreach ($exams as $exam) {
				$exam_department = isset($exam['department']) ? trim((string) $exam['department']) : '';

				if (
					strcasecmp($exam_department, $department_name) === 0 ||
					$exam_department === (string) $department_id
				) {
					$filtered[] = array(
						'id'           => $exam['id'],
						'exam_name'    => $exam['exam_name'],
						'exam_year'    => $exam['exam_year'],
						'exam_year_id' => $exam['exam_year_id'],
						'exam_category' => $exam['exam_category'],
					);
				}
			}

			wp_send_json_success($filtered);
		}
	}

	// Remove the department field before returning the list
	$exams = array_map(
		static function ($exam) {
			unset($exam['department']);
			return $exam;
		},
		$exams
	);

	wp_send_json_success($exams ?: array());
}
add_action('wp_ajax_astgdrmsys_get_exam_names_by_class_and_department', 'ASTGDRMSYS\ResultManagement\get_exam_names_by_class_and_department');
add_action('wp_ajax_nopriv_astgdrmsys_get_exam_names_by_class_and_department', 'ASTGDRMSYS\\ResultManagement\\get_exam_names_by_class_and_department');

/**
 * Retrieves record counts for delete-record previews.
 */
function astgdrmsys_get_delete_record_preview(): void
{
	if (! astgdrmsys_verify_ajax_request()) {
		return;
	}

	check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce');

	if (! current_user_can('manage_options')) {
		wp_send_json_error(__('You do not have sufficient permissions to preview deleted records.', 'result-management-system-for-institutions'));
	}

	global $wpdb;

	$type         = isset($_POST['preview_type']) ? sanitize_key(wp_unslash($_POST['preview_type'])) : 'exam';
	$result_table = esc_sql($wpdb->prefix . 'astgdrmsys_student_result');
	$mark_table   = esc_sql($wpdb->prefix . 'astgdrmsys_mark');

	if ('all' === $type) {
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$students = (int) $wpdb->get_var("SELECT COUNT(*) FROM $result_table");
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$marks = (int) $wpdb->get_var("SELECT COUNT(*) FROM $mark_table");

		wp_send_json_success(
			array(
				'students' => $students,
				'marks'    => $marks,
			)
		);
	}

	$class_id      = filter_input(INPUT_POST, 'class', FILTER_VALIDATE_INT);
	$department_id = filter_input(INPUT_POST, 'department', FILTER_VALIDATE_INT);
	$selected_exam = isset($_POST['exam']) ? sanitize_text_field(wp_unslash($_POST['exam'])) : '';

	if (! $class_id || ! $department_id || '' === $selected_exam) {
		wp_send_json_error(__('Missing class, department, or exam.', 'result-management-system-for-institutions'));
	}

	$exam_parts = array_map('trim', explode(',', $selected_exam));
	if (2 !== count($exam_parts)) {
		wp_send_json_error(__('Invalid exam selection.', 'result-management-system-for-institutions'));
	}

	$exam_id      = absint($exam_parts[0]);
	$exam_year_id = absint($exam_parts[1]);

	if (! $exam_id || ! $exam_year_id) {
		wp_send_json_error(__('Invalid exam selection.', 'result-management-system-for-institutions'));
	}

	// phpcs:ignore WordPress.DB.DirectDatabaseQuery
	$student_ids = array_map(
		'intval',
		$wpdb->get_col(
			$wpdb->prepare(
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				"SELECT sid FROM $result_table WHERE class = %d AND department = %d AND exam_name = %d AND exam_year = %d",
				$class_id,
				$department_id,
				$exam_id,
				$exam_year_id
			)
		)
	);

	$marks = 0;
	if (! empty($student_ids)) {
		$placeholders = implode(', ', array_fill(0, count($student_ids), '%d'));
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$marks = (int) $wpdb->get_var(
			$wpdb->prepare(
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
				"SELECT COUNT(*) FROM $mark_table WHERE sid IN ($placeholders)",
				...$student_ids
			)
		);
	}

	wp_send_json_success(
		array(
			'students' => count($student_ids),
			'marks'    => $marks,
		)
	);
}
add_action('wp_ajax_astgdrmsys_get_delete_record_preview', 'ASTGDRMSYS\ResultManagement\astgdrmsys_get_delete_record_preview');

/**
 * Retrieves subjects that belong to a given exam.
 *
 * @return void
 */
function get_subjects_by_exam(): void
{
	if (! astgdrmsys_verify_ajax_request()) {
		return;
	}

	check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce');

	$exam_id = filter_input(INPUT_POST, 'exam_id', FILTER_VALIDATE_INT);
	if (! $exam_id) {
		wp_send_json_error('Invalid exam ID');
	}

	global $wpdb;

	$exam_table = $wpdb->prefix . 'astgdrmsys_exam_name';

	// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
	$exam = $wpdb->get_row(
		$wpdb->prepare(
			"SELECT class_id, department FROM {$exam_table} WHERE id = %d",
			$exam_id
		),
		ARRAY_A
	);

	if (! $exam) {
		wp_send_json_error('Exam not found');
	}

	$class_id = isset($exam['class_id']) ? (int) $exam['class_id'] : 0;
	if (! $class_id) {
		wp_send_json_error('Exam not found');
	}

	$subjects = astgdrmsys_get_subjects_for_exam($wpdb, $class_id, $exam['department'] ?? '');

	wp_send_json_success($subjects ?: array());
}
add_action('wp_ajax_astgdrmsys_get_subjects_by_exam', 'ASTGDRMSYS\\ResultManagement\\get_subjects_by_exam');
add_action('wp_ajax_nopriv_astgdrmsys_get_subjects_by_exam', 'ASTGDRMSYS\\ResultManagement\\get_subjects_by_exam');

/**
 * Helper to fetch subjects for a specific exam.
 *
 * @param wpdb   $wpdb              The WordPress database abstraction object.
 * @param int    $class_id          The class ID associated with the exam.
 * @param string $department_value  The department value stored with the exam (may be ID or name).
 *
 * @return array<int, array<string, mixed>> List of subjects matching the exam context.
 */
function astgdrmsys_get_subjects_for_exam($wpdb, int $class_id, string $department_value = ''): array
{
	$subjects_table = esc_sql($wpdb->prefix . 'astgdrmsys_subject');

	// $subjects = array();

	if ($department_value !== '') {
		$department_table = esc_sql($wpdb->prefix . 'astgdrmsys_department');

		if (is_numeric($department_value)) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
			$subjects = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT id, subcode, subname, total FROM {$subjects_table} WHERE class = %d AND department = %d ORDER BY subcode ASC",
					$class_id,
					(int) $department_value
				),
				ARRAY_A
			);

			if (! empty($subjects)) {
				return $subjects;
			}

			$department_name = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT department FROM {$department_table} WHERE id = %d",
					(int) $department_value
				)
			);

			if (! empty($department_name)) {
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
				$subjects = $wpdb->get_results(
					$wpdb->prepare(
						"SELECT id, subcode, subname, total FROM {$subjects_table} WHERE class = %d AND department = %s ORDER BY subcode ASC",
						$class_id,
						$department_name
					),
					ARRAY_A
				);

				if (! empty($subjects)) {
					return $subjects;
				}
			}
		} else {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
			$department_id = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT id FROM {$department_table} WHERE LOWER(TRIM(department)) = LOWER(TRIM(%s)) ORDER BY id ASC LIMIT 1",
					$department_value
				)
			);

			if ($department_id) {
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
				$subjects = $wpdb->get_results(
					$wpdb->prepare(
						"SELECT id, subcode, subname, total FROM {$subjects_table} WHERE class = %d AND department = %d ORDER BY subcode ASC",
						$class_id,
						(int) $department_id
					),
					ARRAY_A
				);

				if (! empty($subjects)) {
					return $subjects;
				}
			}

			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
			$subjects = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT id, subcode, subname, total FROM {$subjects_table} WHERE class = %d AND department = %s ORDER BY subcode ASC",
					$class_id,
					$department_value
				),
				ARRAY_A
			);

			if (! empty($subjects)) {
				return $subjects;
			}
		}
		return array();
	}

	// Fallback to class-wide subjects if department-specific lookups fail.
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
	return $wpdb->get_results(
		$wpdb->prepare(
			"SELECT id, subcode, subname, total FROM {$subjects_table} WHERE class = %d ORDER BY subcode ASC",
			$class_id
		),
		ARRAY_A
	);
}

/**
 * Retrieve the global display-name configuration with sensible defaults.
 *
 * @return array<string, string> Associative array of display-name settings.
 */
function astgdrmsys_get_display_name_baseline(): array
{
	$saved_display_names = get_option('astgdrmsys_display_name', array());

	$default_display_names = array(
		'class_display_name'           => 'Class',
		'dept_display_name'            => 'Department',
		'section_display_name'         => 'Section',
		'exam_year_display_name'       => 'Exam Year',
		'exam_name_display_name'       => 'Exam Name',
		'roll_display_name'            => 'Roll No',
		'regno_display_name'           => 'Registration Number',
		'practical_mark_display_name'  => 'Practical Mark',
		'class_mark_display_name'      => 'Class Mark',
		'final_mark_display_name'      => 'Final Mark',
		'total_mark_display_name'      => 'Total Mark',
		'single_mark_display_name'     => 'Exam Mark',
	);

	return wp_parse_args($saved_display_names, $default_display_names);
}

/**
 * Determine the resolved assessment display labels for an exam row.
 *
 * @param array<string, mixed> $exam_row Exam record containing assessment labels and type.
 * @return array<string, string> Resolved assessment labels keyed by column name.
 */
function astgdrmsys_determine_assessment_display_names(array $exam_row): array
{
	$baseline  = astgdrmsys_get_display_name_baseline();
	$exam_type = isset($exam_row['exam_type']) ? (string) $exam_row['exam_type'] : 'single';

	$first  = isset($exam_row['first_assessment_display_name']) ? trim((string) $exam_row['first_assessment_display_name']) : '';
	$second = isset($exam_row['second_assessment_display_name']) ? trim((string) $exam_row['second_assessment_display_name']) : '';
	$third  = isset($exam_row['third_assessment_display_name']) ? trim((string) $exam_row['third_assessment_display_name']) : '';
	$total  = isset($exam_row['total_display_name']) ? trim((string) $exam_row['total_display_name']) : '';

	$defaults_by_type = array(
		'single'    => array(
			'first'  => $baseline['single_mark_display_name'],
			'second' => '',
			'third'  => '',
		),
		'composite' => array(
			'first'  => $baseline['class_mark_display_name'],
			'second' => $baseline['final_mark_display_name'],
			'third'  => '',
		),
		'triple'    => array(
			'first'  => $baseline['practical_mark_display_name'],
			'second' => $baseline['class_mark_display_name'],
			'third'  => $baseline['final_mark_display_name'],
		),
	);

	$fallbacks = $defaults_by_type[$exam_type] ?? $defaults_by_type['single'];

	return array(
		'first_assessment_display_name'  => $first !== '' ? $first : $fallbacks['first'],
		'second_assessment_display_name' => $second !== '' ? $second : ($fallbacks['second'] ?? ''),
		'third_assessment_display_name'  => $third !== '' ? $third : ($fallbacks['third'] ?? ''),
		'total_display_name'             => $total !== '' ? $total : $baseline['total_mark_display_name'],
	);
}

/**
 * Resolve the mark display labels for a specific exam, merging global defaults with exam overrides.
 *
 * @param array<string, mixed> $exam_row Exam record containing assessment labels and type.
 * @return array<string, string> Display labels keyed by usage (practical, class, final, etc.).
 */
function astgdrmsys_resolve_exam_mark_labels(array $exam_row): array
{
	$baseline = astgdrmsys_get_display_name_baseline();
	$resolved = astgdrmsys_determine_assessment_display_names($exam_row);
	$exam_type = isset($exam_row['exam_type']) ? (string) $exam_row['exam_type'] : 'single';

	$labels = $baseline;

	$labels['single_mark_display_name'] = $resolved['first_assessment_display_name'];
	$labels['total_mark_display_name']  = $resolved['total_display_name'];

	if ('triple' === $exam_type) {
		$labels['practical_mark_display_name'] = $resolved['first_assessment_display_name'];
		$labels['class_mark_display_name']      = $resolved['second_assessment_display_name'] !== ''
			? $resolved['second_assessment_display_name']
			: $baseline['class_mark_display_name'];
		$labels['final_mark_display_name']      = $resolved['third_assessment_display_name'] !== ''
			? $resolved['third_assessment_display_name']
			: $baseline['final_mark_display_name'];
	} elseif ('composite' === $exam_type) {
		$labels['class_mark_display_name'] = $resolved['first_assessment_display_name'];
		$labels['final_mark_display_name'] = $resolved['second_assessment_display_name'] !== ''
			? $resolved['second_assessment_display_name']
			: $baseline['final_mark_display_name'];
		$labels['practical_mark_display_name'] = $baseline['practical_mark_display_name'];
	} else {
		$labels['practical_mark_display_name'] = $baseline['practical_mark_display_name'];
		$labels['class_mark_display_name']      = $baseline['class_mark_display_name'];
		$labels['final_mark_display_name']      = $baseline['final_mark_display_name'];
	}

	return array_merge($labels, $resolved);
}

/**
 * Retrieves subjects filtered by class and department.
 */
function get_subjects_by_class_and_department(): void
{
	if (! astgdrmsys_verify_ajax_request()) {
		return;
	}

	check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce');

	$class_id       = filter_input(INPUT_POST, 'class', FILTER_VALIDATE_INT);
	$department_id  = filter_input(INPUT_POST, 'department', FILTER_VALIDATE_INT);

	if (! $class_id || ! $department_id) {
		wp_send_json_error('Invalid class or department ID');
	}

	global $wpdb;

	$subjects = astgdrmsys_get_subjects_for_exam($wpdb, (int) $class_id, (string) $department_id);

	if (empty($subjects)) {
		$department_table = $wpdb->prefix . 'astgdrmsys_department';
		$department_name  = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT department FROM {$department_table} WHERE id = %d",
				$department_id
			)
		);

		if (! empty($department_name)) {
			$subjects = astgdrmsys_get_subjects_for_exam($wpdb, (int) $class_id, $department_name);
		}
	}

	if (! is_array($subjects)) {
		$subjects = array();
	}

	wp_send_json_success($subjects ?: array());
}
add_action('wp_ajax_astgdrmsys_get_subjects_by_class_and_department', 'ASTGDRMSYS\ResultManagement\get_subjects_by_class_and_department');
add_action('wp_ajax_nopriv_astgdrmsys_get_subjects_by_class_and_department', 'ASTGDRMSYS\ResultManagement\get_subjects_by_class_and_department');

/**
 * Retrieves subjects by class.
 *
 * This function fetches and returns a list of  filtered subjects based on the provided class ID only .
 *
 * @return void
 */
function get_subjects_by_class(): void
{
	if (!astgdrmsys_verify_ajax_request()) {
		return;
	}
	check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce');

	$class_id = filter_input(INPUT_POST, 'class', FILTER_VALIDATE_INT);
	if (!$class_id) {
		wp_send_json_error('Invalid class ID');
	}

	global $wpdb;
	$subjects = $wpdb->get_results($wpdb->prepare(
		"SELECT id, subcode, subname FROM {$wpdb->prefix}astgdrmsys_subject WHERE class = %d",
		$class_id
	));

	// Return the subjects
	wp_send_json_success($subjects ?: []);
}
add_action('wp_ajax_astgdrmsys_get_subjects_by_class', 'ASTGDRMSYS\ResultManagement\get_subjects_by_class');
add_action('wp_ajax_nopriv_astgdrmsys_get_subjects_by_class', 'ASTGDRMSYS\ResultManagement\get_subjects_by_class');

/**
 * Retrieves published exams by class.
 *
 * This function fetches and returns a list of published exams based on the provided class ID.
 *
 * @return void
 */
function get_publish_exam_by_class(): void
{
	if (!astgdrmsys_verify_ajax_request()) {
		return;
	}
	check_ajax_referer('astgdrmsys_ajax_nonce', 'nonce');

	$class_id = filter_input(INPUT_POST, 'class', FILTER_VALIDATE_INT);
	if (!$class_id) {
		wp_send_json_error('Invalid class ID');
	}

	global $wpdb;
	$exams = $wpdb->get_results($wpdb->prepare(
		"SELECT id, exam_name, exam_year, exam_year_id FROM {$wpdb->prefix}astgdrmsys_exam_name WHERE class_id = %d AND result_publish_status = 1",
		$class_id
	));

	wp_send_json_success($exams ?: []);
}
add_action('wp_ajax_astgdrmsys_get_publish_exam_by_class', 'ASTGDRMSYS\ResultManagement\get_publish_exam_by_class');
add_action('wp_ajax_nopriv_astgdrmsys_get_publish_exam_by_class', 'ASTGDRMSYS\ResultManagement\get_publish_exam_by_class');

/**
 * Function to handle the activation of the plugin.
 *
 * This function is called when the plugin is activated. It performs necessary
 * setup tasks such as creating database tables, setting default options, etc.
 *
 * @return void
 */
function astgdrmsys_activate_plugin(): void
{
	require_once ASTGDRMSYS_PLUGIN_DIR . 'installation.php';

	// run the installation routine to create database tables and set default options
	\ASTGDRMSYS\ResultManagement\astgdrmsys_run_installation_routine();

	// Create upload directory for results
	$upload_dir = wp_upload_dir();
	$result_dir = $upload_dir['basedir'] . '/astgdrmsys-results';

	if (! file_exists($result_dir)) {
		wp_mkdir_p($result_dir);
	}
}
register_activation_hook(__FILE__, 'ASTGDRMSYS\ResultManagement\astgdrmsys_activate_plugin');

/**
 * Runs database upgrades when plugin files are updated without a deactivate/reactivate cycle.
 */
function astgdrmsys_maybe_upgrade_database(): void
{
	$installed_version = (string) get_option('astgdrmsys_db_version', '');

	if ($installed_version === ASTGDRMSYS_VERSION) {
		return;
	}

	require_once ASTGDRMSYS_PLUGIN_DIR . 'installation.php';
	\ASTGDRMSYS\ResultManagement\astgdrmsys_run_installation_routine();
}
add_action('admin_init', 'ASTGDRMSYS\ResultManagement\astgdrmsys_maybe_upgrade_database');

/**
 * Function to handle the deactivation of the plugin.
 *
 * This function is called when the plugin is deactivated. It performs necessary
 * cleanup tasks such as removing database tables, deleting options, etc.
 *
 * @return void
 */
function astgdrmsys_uninstall_plugin(): void
{
	global $wpdb;

	$tables = array(
		'astgdrmsys_student_result',
		'astgdrmsys_students',
		'astgdrmsys_student_enrollments',
		'astgdrmsys_school_info',
		'astgdrmsys_general_settings',
		'astgdrmsys_view_settings',
		'astgdrmsys_mark',
		'astgdrmsys_retake_marks',
		'astgdrmsys_subject',
		'astgdrmsys_class',
		'astgdrmsys_department',
		'astgdrmsys_section',
		'astgdrmsys_exam_name',
		'astgdrmsys_exam_year',
		'astgdrmsys_grade_system',
	);

	foreach ($tables as $table) {
		// Sanitize the table name
		$safe_table = $wpdb->prefix . sanitize_key($table);
		// Drop the table
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$wpdb->query("DROP TABLE IF EXISTS `$safe_table`");
	}

	// Clean up upload directory
	$upload_dir = wp_upload_dir();
	$result_dir = $upload_dir['basedir'] . '/astgdrmsys-results';

	// Load WP_Filesystem
	global $wp_filesystem;
	// Check if WP_Filesystem is already loaded
	if (empty($wp_filesystem)) {
		require_once ABSPATH . 'wp-admin/includes/file.php';
		WP_Filesystem();
	}

	// Check if the result directory exists
	if ($wp_filesystem->is_dir($result_dir)) {
		$files = glob($result_dir . '/*');

		// Delete all files in the directory
		foreach ($files as $file) {
			if ($wp_filesystem->is_file($file)) {
				$wp_filesystem->delete($file);
			}
		}

		// Remove the directory
		$wp_filesystem->rmdir($result_dir);
	}
}
register_uninstall_hook(__FILE__, 'ASTGDRMSYS\ResultManagement\astgdrmsys_uninstall_plugin');

/**
 * Handles logging for both 'astgdrmsys_debug_log' and 'astgdrmsys_log_error' custom actions.
 *
 * This function writes log messages to a dedicated log file inside the uploads directory
 * (`wp-content/uploads/astgdrmsys-logs/rms.log`) if both WP_DEBUG and WP_DEBUG_LOG are enabled.
 *
 * Benefits:
 * - Safe location (won’t be deleted on plugin updates)
 * - Multisite and security friendly
 *
 * @param string $message The debug/error message to be logged.
 */
function astgdrmsys_handle_debug_log($message)
{
	if (! WP_DEBUG || ! WP_DEBUG_LOG) {
		return;
	}

	$upload_dir = wp_upload_dir();
	$log_dir    = trailingslashit($upload_dir['basedir']) . 'astgdrmsys-logs';
	$log_file   = trailingslashit($log_dir) . 'rms.log';

	// Recursively create directory if it doesn't exist
	if (! file_exists($log_dir)) {
		wp_mkdir_p($log_dir);
	}

	$log_entry = current_time('mysql') . ' - ' . $message . PHP_EOL;

	file_put_contents($log_file, $log_entry, FILE_APPEND);
}

// Register both logging hooks to the same handler
add_action('astgdrmsys_debug_log', 'ASTGDRMSYS\ResultManagement\astgdrmsys_handle_debug_log');
add_action('astgdrmsys_log_error', 'ASTGDRMSYS\ResultManagement\astgdrmsys_handle_debug_log');

/**
 * Shortcode handler function to display results.
 *
 * @param array $atts Shortcode attributes.
 * @return string The result output to be displayed.
 */
function astgdrmsys_show_shortcode($atts): string
{
        $atts = shortcode_atts(array(
                'sclass'      => '',
                'sdepartment' => '',
                'ssection'    => '',
                's_exam_name' => '',
                'require_registration' => '',
        ), $atts, 'astgdrmsys_show_result');

        ob_start();
        require_once ASTGDRMSYS_PLUGIN_DIR . 'menu-files/show-result/show-result.php';
        return ob_get_clean();
}
add_shortcode('astgdrmsys_show_result', 'ASTGDRMSYS\ResultManagement\astgdrmsys_show_shortcode');
