<?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.
 */

/**
 * This file is part of the Result Management System for Institutions plugin.
 *
 * It ensures that the file is being accessed through WordPress by checking if the ABSPATH constant is defined.
 * If ABSPATH is not defined, the script will exit to prevent unauthorized access.
 */
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class ASTGDRMSYS_Department_Manager
 *
 * This class is responsible for managing department-related functionalities
 * within the RMS (Result Management System for Institutions) plugin.
 *
 * @package ResultManagementSystemResultManagement
 * @subpackage DepartmentManagement
 * @since 1.0.0
 */
class ASTGDRMSYS_Department_Manager {

	private $wpdb;
	private $prefix;
	private $messages = array();

	/**
	 * Constructor for the class.
	 *
	 * This method initializes the class and sets up any necessary properties or methods.
	 */
	public function __construct() {
		global $wpdb;
		$this->wpdb   = $wpdb;
		$this->prefix = $wpdb->prefix;

		// Handle actions
		$this->astgdrmsys_handle_actions();
	}

	/**
	 * Handles the actions related to the department addition process.
	 *
	 * This function is responsible for managing the various actions that can be
	 * performed when adding a new department within the plugin.
	 *
	 * @return void
	 */
	private function astgdrmsys_handle_actions() {

		// Check if this is a POST request
		if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'POST' ) {
			// Nonce check and sanitization
			if ( ! isset( $_POST['astgdrmsys_department_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['astgdrmsys_department_nonce'] ) ), 'astgdrmsys_department_action' ) ) {
				wp_die( esc_html__( 'Invalid request. Please refresh and try again.', 'result-management-system-for-institutions' ) );
			}
		}

		// Handle messages
		$message_types = array(
			'edit' => 'Department Updated Successfully',
			'del'  => 'Department Deleted Successfully',
			'add'  => 'Department Added Successfully',
		);

		foreach ( $message_types as $type => $msg ) {
			if ( isset( $_GET[ $type ] ) && $_GET[ $type ] === 'true' ) {
				$this->add_message( 'success', $msg );
			}
		}

		// Handle form submissions
		if ( isset( $_POST['updatesubmit'] ) ) {
			$this->update_department();
		} elseif ( isset( $_POST['addsubmit'] ) ) {
			$this->add_department();
		}
	}

	/**
	 * Adds a message to the system.
	 *
	 * @param string $type The type of the message (e.g., 'error', 'success', 'info').
	 * @param string $message The content of the message to be added.
	 */
	private function add_message( $type, $message ) {
		$this->messages[] = array(
			'type'    => $type,
			'message' => $message,
		);
	}

	/**
	 * Retrieves the list of classes.
	 *
	 * This private function is responsible for fetching and returning
	 * an array of classes. The specific implementation details and
	 * the source of the classes are not provided in this snippet.
	 *
	 * @return array An array of classes.
	 */
	private function get_classes( $wpdb ) {
		$cache_key = 'astgdrmsys_class_list';
		$classes   = wp_cache_get( $cache_key );

		if ( $classes === false ) {
			$table = esc_sql( $wpdb->prefix . 'astgdrmsys_class' );
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
			$classes = $wpdb->get_results( "SELECT * FROM `$table` ORDER BY id ASC" );
			wp_cache_set( $cache_key, $classes );
		}

		return $classes;
	}

	/**
	 * Retrieves a list of departments.
	 *
	 * This function fetches and returns an array of departments.
	 *
	 * @return array An array of departments.
	 */
        private function get_departments( $wpdb ) {
                $department_table = esc_sql( $wpdb->prefix . 'astgdrmsys_department' );
                $sql = "SELECT id, department FROM $department_table ORDER BY department ASC, id ASC";

                // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery
                return $this->wpdb->get_results( $sql, ARRAY_A );
        }

	private function department_exists( string $department, int $exclude_id = 0 ): bool {
		$table = esc_sql( $this->prefix . 'astgdrmsys_department' );
		$sql   = "SELECT id FROM {$table} WHERE LOWER(TRIM(department)) = LOWER(TRIM(%s))";
		$args  = array( $department );

		if ( $exclude_id > 0 ) {
			$sql   .= ' AND id <> %d';
			$args[] = $exclude_id;
		}

		return (int) $this->wpdb->get_var( $this->wpdb->prepare( $sql, $args ) ) > 0;
	}

	/**
	 * Deletes a department based on the provided ID.
	 *
	 * @param int $id The ID of the department to be deleted.
	 *
	 * @return void
	 */
	private function delete_department( $id ) {
		$this->wpdb->query( 'START TRANSACTION' );

		try {
			$this->wpdb->delete(
				$this->prefix . 'astgdrmsys_department',
				array( 'id' => $id ),
				array( '%d' )
			);

			wp_cache_delete( 'astgdrmsys_departments' );
			$this->wpdb->query( 'COMMIT' );
			wp_safe_redirect(
				add_query_arg(
					array(
						'page' => 'astgdrmsys-department',
						'del'  => 'true',
					),
					admin_url( 'admin.php' )
				)
			);
			exit;
		} catch ( Exception $e ) {
			$this->wpdb->query( 'ROLLBACK' );
			$this->add_message( 'error', 'Error deleting department: ' . esc_html( $e->getMessage() ) );
		}
	}

	/**
	 * Updates the department information in the database.
	 *
	 * This function handles the logic for updating an existing department's details.
	 * It retrieves the department data from the request, validates it, and then
	 * updates the corresponding record in the database.
	 *
	 * @return void
	 */
	private function update_department() {
		// Check nonce first
		if ( ! isset( $_POST['astgdrmsys_department_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['astgdrmsys_department_nonce'] ) ), 'astgdrmsys_department_action' ) ) {
			$this->add_message( 'error', __( 'Invalid request. Please try again.', 'result-management-system-for-institutions' ) );
			return;
		}

		// Validate required fields
		if ( ! isset( $_POST['department_id'], $_POST['updatedepartment'] ) ) {
			$this->add_message( 'error', __( 'Missing required fields.', 'result-management-system-for-institutions' ) );
			return;
		}

		// Sanitize inputs
		$id         = absint( wp_unslash( $_POST['department_id'] ) );
		$department = sanitize_text_field( wp_unslash( $_POST['updatedepartment'] ) );

		if ( $department === '' ) {
			$this->add_message( 'error', __( 'Department name is required.', 'result-management-system-for-institutions' ) );
			return;
		}

		if ( $this->department_exists( $department, $id ) ) {
			$this->add_message( 'error', __( 'A department with this name already exists.', 'result-management-system-for-institutions' ) );
			return;
		}

		// Update record
		$updated = $this->wpdb->update(
			$this->prefix . 'astgdrmsys_department',
			array(
				'department' => $department,
				'class'      => 0,
			),
			array( 'id' => $id ),
			array( '%s', '%d' ),
			array( '%d' )
		);

		if ( $updated !== false ) {
			wp_cache_delete( 'astgdrmsys_departments' );
			wp_safe_redirect(
				add_query_arg(
					array(
						'page' => 'astgdrmsys-department',
						'edit' => 'true',
					),
					admin_url( 'admin.php' )
				)
			);
			exit;
		}
	}

	/**
	 * Adds a new department to the system.
	 *
	 * This function handles the logic for adding a new department, including
	 * validation and database insertion.
	 *
	 * @return void
	 */
	private function add_department() {
		// Check nonce and fields first
		if ( ! isset( $_POST['astgdrmsys_department_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['astgdrmsys_department_nonce'] ) ), 'astgdrmsys_department_action' ) ) {
			$this->add_message( 'error', __( 'Invalid request. Please try again.', 'result-management-system-for-institutions' ) );
			return;
		}

		// Sanitize and validate input
		$department = isset( $_POST['department'] ) ? sanitize_text_field( wp_unslash( $_POST['department'] ) ) : '';

		if ( $department === '' ) {
			$this->add_message( 'error', __( 'Department name is required.', 'result-management-system-for-institutions' ) );
			return;
		}

		if ( $this->department_exists( $department ) ) {
			$this->add_message( 'error', __( 'A department with this name already exists.', 'result-management-system-for-institutions' ) );
			return;
		}

		// Insert into DB
		$inserted = $this->wpdb->insert(
			$this->prefix . 'astgdrmsys_department',
			array(
				'department' => $department,
				'class'      => 0,
			),
			array( '%s', '%d' )
		);

		if ( $inserted ) {
			wp_cache_delete( 'astgdrmsys_departments' );
			wp_safe_redirect(
				add_query_arg(
					array(
						'page' => 'astgdrmsys-department',
						'add'  => 'true',
					),
					admin_url( 'admin.php' )
				)
			);
			exit;
		} else {
			$this->add_message( 'error', 'Failed to add department.' );
		}
	}


	/**
	 * Renders the add department page.
	 *
	 * This function is responsible for rendering the user interface for adding a new department
	 * within the RMS Result Management plugin.
	 *
	 * @return void
	 */
	public function astgdrmsys_dept_render() {
		global $wpdb;

		// Nonce verification for POST requests
		if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'POST' ) {
			check_admin_referer( 'astgdrmsys_department_action', 'astgdrmsys_department_nonce' );
		}

		// Display messages
		foreach ( $this->messages as $message ) { ?>
			<div class="notice notice-<?php echo esc_attr( $message['type'] ); ?> is-dismissible">
				<p><?php echo esc_html( $message['message'] ); ?></p>
			</div>
			<?php
		}

		// Handle delete securely
		if ( isset( $_GET['delid'], $_GET['astgdrmsys_nonce'] ) ) {
			$delid = absint( wp_unslash( $_GET['delid'] ) );
			$nonce = sanitize_text_field( wp_unslash( $_GET['astgdrmsys_nonce'] ) );

			if ( wp_verify_nonce( $nonce, 'astgdrmsys_department_action' ) && current_user_can( 'manage_options' ) ) {
				$this->delete_department( $delid );
				return;
			} else {
				wp_die( esc_html__( 'Unauthorized deletion attempt.', 'result-management-system-for-institutions' ) );
			}
		}

		// Check if 'editid' and 'astgdrmsys_nonce' exist in GET before using
		if ( isset( $_GET['editid'], $_GET['astgdrmsys_nonce'] ) && $_GET['editid'] !== '' ) {
			// Sanitize and validate the edit ID
			$editid = isset( $_GET['editid'] ) ? absint( wp_unslash( $_GET['editid'] ) ) : 0;
			$nonce  = isset( $_GET['astgdrmsys_nonce'] ) ? sanitize_text_field( wp_unslash( $_GET['astgdrmsys_nonce'] ) ) : '';

			// Verify the nonce and permission
			if ( wp_verify_nonce( $nonce, 'astgdrmsys_department_action' ) && current_user_can( 'manage_options' ) ) {
				$this->astgdrmsys_render_edit_form( $editid );
			} else {
				wp_die( esc_html__( 'Unauthorized access or invalid nonce.', 'result-management-system-for-institutions' ) );
			}
		} else {
			$this->astgdrmsys_render_department_list( $wpdb );
		}
	}

	/**
	 * Renders the edit form for the department.
	 *
	 * This function generates and displays the HTML form used to edit a department's details.
	 *
	 * @return void
	 */
	private function astgdrmsys_render_edit_form( $id ) {
		global $wpdb;
		// create a cache key for the department
		$cache_key  = 'department_' . $id;
		$department = wp_cache_get( $cache_key );

		if ( $department === false ) {
            // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery
			$department = $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}astgdrmsys_department WHERE id = %d",
					$id
				),
				ARRAY_A
			);

			wp_cache_set( $cache_key, $department );
		}

		// Show error if department not found
		if ( ! $department ) {
			wp_die( 'Department not found' );
		}

		?>
		<div class="wrap">
			<h1><?php esc_html_e( 'Edit Department', 'result-management-system-for-institutions' ); ?></h1>
			<form method="post" action="">
				<?php wp_nonce_field( 'astgdrmsys_department_action', 'astgdrmsys_department_nonce' ); ?>
				<input type="hidden" name="department_id" value="<?php echo esc_attr( $id ); ?>">

				<table class="form-table">
					<tr>
						<th><label for="updatedepartment"><?php esc_html_e( 'Department Name', 'result-management-system-for-institutions' ); ?></label></th>
						<td>
							<input type="text" name="updatedepartment" id="updatedepartment"
								value="<?php echo esc_attr( $department['department'] ); ?>"
								class="regular-text" required>
						</td>
					</tr>
				</table>
				<?php submit_button( __( 'Update Department', 'result-management-system-for-institutions' ), 'primary', 'updatesubmit' ); ?>
				<button type="button"
					class="btn btn-danger ml-2"
					onclick="window.history.back();"><?php esc_html_e( 'Cancel', 'result-management-system-for-institutions' ); ?>
				</button>
			</form>
		</div> 
		<?php
	}

			/**
			 * Renders the list of departments.
			 *
			 * This function generates and displays the list of departments
			 * in the department management section of the plugin.
			 *
			 * @return void
			 */
	private function astgdrmsys_render_department_list( $wpdb ) {
		$departments = $this->get_departments( $wpdb );
		?>
		<div class="wrap astgdrmsys-premium-wrap">
			<div class="premium-page-header">
				<div class="page-header-text">
					<h1><?php esc_html_e( 'Departments', 'result-management-system-for-institutions' ); ?></h1>
					<p>Manage the departments in your institution.</p>
				</div>
				<div class="page-header-actions">
					<button onclick="document.getElementById('add-dept-modal').style.display='block'" class="hero-btn primary-btn">
						<i class="dashicons dashicons-plus"></i> <?php esc_html_e( 'Add New', 'result-management-system-for-institutions' ); ?>
					</button>
				</div>
			</div>

			<?php if ( ! empty( $departments ) ) : ?>
				<table class="styled-table">
					<thead>
						<tr>
							<th><?php esc_html_e( 'ID', 'result-management-system-for-institutions' ); ?></th>
							<th><?php esc_html_e( 'Department', 'result-management-system-for-institutions' ); ?></th>
							<th><?php esc_html_e( 'Actions', 'result-management-system-for-institutions' ); ?></th>
						</tr>
					</thead>
					<tbody>
						<?php
						foreach ( $departments as $dept ) :
							// Convert $dept to array if it's an object
							if ( is_object( $dept ) ) {
								$dept = (array) $dept;
							}
							$nonce_key = wp_create_nonce( 'astgdrmsys_department_action' );
							?>
							<tr>
								<td><?php echo esc_html( $dept['id'] ); ?></td>
								<td><?php echo esc_html( $dept['department'] ); ?></td>
								<td>
									<a href="
									<?php
									echo esc_url(
										add_query_arg(
											array(
												'page'   => 'astgdrmsys-department',
												'editid' => $dept['id'],
												'astgdrmsys_nonce' => $nonce_key,
											)
										)
									);
									?>
												"
										class="button button-small">
										<span class="dashicons dashicons-edit"></span>
									</a>
									<a href="
									<?php
									echo esc_url(
										add_query_arg(
											array(
												'page'  => 'astgdrmsys-department',
												'delid' => $dept['id'],
												'astgdrmsys_nonce' => $nonce_key,
											)
										)
									);
									?>
									"
										onclick="return confirm('<?php esc_attr_e( 'Do you really want to delete the department?', 'result-management-system-for-institutions' ); ?>');"
										class="button button-small button-link-delete">
										<span class="dashicons dashicons-trash"></span>
									</a>
								</td>
							</tr>
						<?php endforeach; ?>
					</tbody>
				</table>
			<?php else : ?>
				<div class="notice notice-warning">
					<p><?php esc_html_e( 'No departments found.', 'result-management-system-for-institutions' ); ?></p>
				</div>
			<?php endif; ?>

			<!-- Add Department Modal -->
			<?php $this->astgdrmsys_render_add_modal(); ?>
		</div> 
		<?php
	}

			/**
			 * Renders the modal for adding a department.
			 *
			 * @param array $classes An array of CSS classes to apply to the modal.
			 */
	private function astgdrmsys_render_add_modal() {

		?>
		<div id="add-dept-modal" class="modal">
			<div class="modal-content">
				<span class="close"
					onclick="document.getElementById('add-dept-modal').style.display='none'">&times;</span>
				<h2><?php esc_html_e( 'Add Department', 'result-management-system-for-institutions' ); ?></h2>
				<form method="post" action="">
			<?php wp_nonce_field( 'astgdrmsys_department_action', 'astgdrmsys_department_nonce' ); ?>
					<div class="form-field">
						<label for="department"><?php esc_html_e( 'Department Name:', 'result-management-system-for-institutions' ); ?></label>
						<input type="text" name="department" id="department" required class="regular-text">
					</div>
					<div class="button-group">
						<?php submit_button( __( 'Add Department', 'result-management-system-for-institutions' ), 'primary', 'addsubmit' ); ?>
						<button type="button" class="button"
							onclick="document.getElementById('add-dept-modal').style.display='none'">
							<?php esc_html_e( 'Cancel', 'result-management-system-for-institutions' ); ?>
						</button>
					</div>
				</form>
			</div>
		</div> <?php
	}
}
		/**
		 *
		 * This script initializes and renders the department management page.
		 *
		 * It creates an instance of the ASTGDRMSYS_Department_Manager class and calls its render method to display the page.
		 */
		$department_manager = new ASTGDRMSYS_Department_Manager();
		$department_manager->astgdrmsys_dept_render();
?>
