<?php
/**
 * Handles task-related operations such as creation, assignment, and updates.
 *
 * @package voidempo
 */
class voidempo_Task {
	/**
	 * Constructor for the voidempo_Task class.
	 *
	 * Initializes the task functionality by setting up necessary hooks,
	 * loading dependencies, or preparing default values.
	 */
	public function __construct() {
		add_action( 'wp_ajax_voidempo_create_task', array( $this, 'voidempo_create_task' ) );
	
		add_action( 'wp_ajax_voidempo_get_eods_databydate', array( $this, 'voidempo_get_eods_databydate' ) );
	
		add_action( 'wp_ajax_voidempo_get_tasks_by_project', array( $this, 'voidempo_get_tasks_by_project' ) );

		add_action( 'wp_ajax_voidempo_insert_eod_data', array( $this, 'voidempo_insert_eod_data' ) );

		add_action( 'wp_ajax_voidempo_get_project_members', array( $this, 'voidempo_get_project_members' ) );

		add_action( 'wp_ajax_voidempo_add_project_ajax', array( $this, 'voidempo_add_project_ajax' ) );

		add_action( 'wp_ajax_voidempo_fetch_all_projects', array( $this, 'voidempo_fetch_all_projects' ) );

		add_action( 'wp_ajax_voidempo_get_single_project', array( $this, 'voidempo_get_single_project' ) );

		add_action( 'wp_ajax_voidempo_update_project', array( $this, 'voidempo_update_project' ) );

		add_action( 'wp_ajax_voidempo_delete_project', array( $this, 'voidempo_delete_project' ) );

		add_action( 'wp_ajax_voidempo_user_registration', array( $this, 'voidempo_user_registration' ) );

		add_action( 'wp_ajax_voidempo_fetch_user_data', array( $this, 'voidempo_fetch_user_data' ) );

		add_action( 'wp_ajax_voidempo_get_user_details', array( $this, 'voidempo_get_user_details' ) );

		add_action( 'wp_ajax_voidempo_update_user_details', array( $this, 'voidempo_update_user_details' ) );

		add_action( 'wp_ajax_voidempo_delete_user_details', array( $this, 'voidempo_delete_user_details' ) );

		add_action( 'wp_ajax_voidempo_check_is_manager', array( $this, 'voidempo_check_is_manager' ) );

		add_action( 'wp_ajax_voidempo_get_project_tasks', array( $this, 'voidempo_get_project_tasks' ) );

		add_action( 'wp_ajax_voidempo_delete_eod', array( $this, 'voidempo_delete_eod' ) );

		add_action( 'wp_ajax_voidempo_get_task_details_callback', array( $this, 'voidempo_get_task_details_callback' ) );

		add_action( 'wp_ajax_voidempo_get_eod_data', array( $this, 'voidempo_get_eod_data' ) );

		add_action( 'wp_ajax_voidempo_update_eod_data', array( $this, 'voidempo_update_eod_data' ) );

		add_action( 'wp_ajax_voidempo_update_task_details', array( $this, 'voidempo_update_task_details_callback' ) );

		add_action( 'wp_ajax_voidempo_usertask_delete', array( $this, 'voidempo_usertask_delete' ) );
		
	}
	/**
	 * AJAX handler to add a new project.
	 *
	 * This function processes an AJAX request to create a new project entry.
	 * It typically receives data such as project title, description, start and end dates,
	 * assigned manager, and members. Validates and inserts the data into the database,
	 * then returns a JSON response.
	 *
	 * @return void Outputs JSON response and terminates.
	 */
	public function voidempo_add_project_ajax() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_safe_redirect( wp_login_url() );
			exit;
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}


		global $wpdb;
		if ( empty( $_POST['project_title'] ) ) {
			wp_send_json(
				array(
					'success' => false,
					'message' => 'Project title is required.',
				)
			);
			wp_die();
		}

		$project_title               = sanitize_text_field( wp_unslash( $_POST['project_title'] ) );
		$project_desc                = isset( $_POST['project_description'] ) ? sanitize_textarea_field( wp_unslash( $_POST['project_description'] ) ) : '';
		$voidempo_project_start_date = isset( $_POST['voidempo_project_start_date'] ) ? sanitize_text_field( wp_unslash( $_POST['voidempo_project_start_date'] ) ) : '';
		$voidempo_project_end_date   = isset( $_POST['voidempo_project_end_date'] ) ? sanitize_text_field( wp_unslash( $_POST['voidempo_project_end_date'] ) ) : '';
		$voidempo_project_manager    = isset( $_POST['voidempo_project_manager'] ) ? sanitize_text_field( wp_unslash( $_POST['voidempo_project_manager'] ) ) : '';
		$voidempo_project_members    = isset( $_POST['voidempo_project_members'] )
			? implode( ',', array_map( 'sanitize_text_field', wp_unslash( $_POST['voidempo_project_members'] ) ) )
			: '';
		$voidempo_project_status     = isset( $_POST['voidempo_project_status'] ) ? sanitize_text_field( wp_unslash( $_POST['voidempo_project_status'] ) ) : '';

		$new_project = array(
			'post_title'   => sanitize_text_field( wp_unslash( $_POST['project_title'] ) ),
			'post_content' => sanitize_textarea_field( wp_unslash( $_POST['project_description'] ) ),
			'post_status'  => 'publish',
			'post_type'    => 'voidempo_projects',
			'post_author'  => get_current_user_id(),
		);

		$post_id = wp_insert_post( $new_project );

		if ( $post_id ) {
			if ( ! empty( $_POST['voidempo_project_start_date'] ) ) {
				update_post_meta( $post_id, 'voidempo_project_start_date', sanitize_text_field( wp_unslash( $_POST['voidempo_project_start_date'] ) ) );
			}

			if ( ! empty( $_POST['voidempo_project_end_date'] ) ) {
				update_post_meta( $post_id, 'voidempo_project_end_date', sanitize_text_field( wp_unslash( $_POST['voidempo_project_end_date'] ) ) );
			}

			if ( ! empty( $_POST['voidempo_project_manager'] ) ) {
				update_post_meta( $post_id, 'voidempo_project_manager', sanitize_text_field( wp_unslash( $_POST['voidempo_project_manager'] ) ) );
			}

			if ( ! empty( $_POST['voidempo_project_members'] ) ) {
				$member_ids = array_map( 'sanitize_text_field', wp_unslash( $_POST['voidempo_project_members'] ) );
				update_post_meta( $post_id, 'voidempo_project_members', implode( ',', $member_ids ) );
			}

			if ( ! empty( $_POST['voidempo_project_status'] ) ) {
				update_post_meta( $post_id, 'voidempo_project_status', sanitize_text_field( wp_unslash( $_POST['voidempo_project_status'] ) ) );
			}

			$wpdb->insert(
				$wpdb->prefix . 'voidempo_projects',
				array(
					'project_title'   => get_the_title( $post_id ),
					'project_desc'    => $project_desc,
					'related_post_id' => $post_id,
					'member_id'       => $voidempo_project_members,
					'manager_id'      => $voidempo_project_manager,
					'status'          => $voidempo_project_status,
					'start_date'      => $voidempo_project_start_date,
					'end_date'        => $voidempo_project_end_date,
					'date_created'    => gmdate( 'Y-m-d H:i:s' ),
				)
			);
			$user_id = get_current_user_ID();
			wp_send_json_success( array( 'message' => 'Project added successfully.' ) );

		} else {
			wp_send_json(
				array(
					'success' => false,
					'message' => 'Failed to add project.',
				)
			);
		}

		wp_die();
	}

	/**
	 * AJAX handler to check if the current user is a manager.
	 *
	 * This function verifies whether the logged-in user has the 'manager' role.
	 * It returns a JSON response indicating true or false.
	 *
	 * @return void Outputs a JSON response and exits.
	 */
	public function voidempo_check_is_manager() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_safe_redirect( wp_login_url() );
			exit;
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' )  || current_user_can( 'voidempo_employee_access' )) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		global $wpdb;
		$project_id = '';

		if ( isset( $_POST['project_id'] ) ) {
			$project_id = sanitize_text_field( wp_unslash( $_POST['project_id'] ) );
		}
		$is_manager = voidempo_fn_check_is_manager_( $project_id, get_current_user_ID() );

		if ( 'is_manager' === $is_manager ) {
			$voidempo_project_members  = explode( ',', get_post_meta( $project_id, 'voidempo_project_members', true ) );
			$voidempo_project_managers = explode( ',', get_post_meta( $project_id, 'voidempo_project_manager', true ) );

			$all_members = array_merge( $voidempo_project_managers, $voidempo_project_members );
			?>
			<label for="voidempo_taskc_assign_mem">Assign Members (If only you then please assign only your name to task)</label>
			<select class="voidempo_taskc_assign_mem" id="voidempo_taskc_assign_mem" name="voidempo_taskc_assign_mem[]" multiple>
				<?php
				foreach ( $all_members as $voidempo_project_members_id ) {
					$user_data = get_user_by( 'id', $voidempo_project_members_id );
					if ( get_user_meta( $user_data->ID, '_employee_disabled', true ) != 1 ) {
						?>
							<option value="<?php echo esc_attr( $user_data->ID ); ?>"><?php echo esc_html( $user_data->display_name ); ?></option>
						<?php
					}
				}
				?>
			</select>
			<?php
		}
		wp_die();
	}
	/**
	 * Retrieves members assigned to a specific project.
	 *
	 * This function returns a list of users who are associated with the given project,
	 * including their user IDs, names, and possibly roles or assignments.
	 *
	 * @param int $project_id The ID of the project.
	 * @return array Array of user data assigned to the project.
	 */
	public function voidempo_get_project_members() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_safe_redirect( wp_login_url() );
			exit;
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ||  current_user_can( 'voidempo_employee_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		$project_id = isset( $_POST['project_id'] ) ? sanitize_text_field( wp_unslash( $_POST['project_id'] ) ) : '';

		$project_id = sanitize_text_field( $project_id );

		$voidempo_project_managers = explode( ',', get_post_meta( $project_id, 'voidempo_project_manager', true ) );
		$voidempo_project_members  = explode( ',', get_post_meta( $project_id, 'voidempo_project_members', true ) );

		$all_members = array_merge( $voidempo_project_managers, $voidempo_project_members );

		$managers_html = '';
		$members_html  = '';

		foreach ( $all_members as $voidempo_project_member_id ) {
			$user_data = get_user_by( 'id', $voidempo_project_member_id );

			if ( get_user_meta( $user_data->ID, '_employee_disabled', true ) != 1 ) {
				$managers_html .= '<option value="' . $user_data->ID . '">' . $user_data->display_name . '</option>';
				$members_html  .= '<option value="' . $user_data->ID . '">' . $user_data->display_name . '</option>';
			}
		}

		wp_send_json(
			array(
				'managers' => $managers_html,
				'members'  => $members_html,
			)
		);
		wp_die();
	}

	/**
	 * AJAX handler for creating a new task.
	 *
	 * This method processes an AJAX request to create a task, including fields such as
	 * task title, assigned user, due date, project ID, and status. It validates input,
	 * saves the task to the database, and returns a JSON response.
	 *
	 * @return void Outputs JSON response and terminates script execution.
	 */
	public function voidempo_create_task() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_safe_redirect( wp_login_url() );
			exit;
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) || current_user_can( 'voidempo_employee_access' )) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		global $wpdb;
		voidempo_default_time_zone_set_();

		$project_id = isset( $_POST['project_id'] ) ? intval( $_POST['project_id'] ) : 0;
		$member_ids = isset( $_POST['member_ids'] ) ? array_map( 'intval', (array) $_POST['member_ids'] ) : array();

		if ( empty( $member_ids ) ) {
			$member_ids = array( get_current_user_ID() );
		}

		$task_status = isset( $_POST['voidempo_taskc_status'] ) ? sanitize_text_field( wp_unslash( $_POST['voidempo_taskc_status'] ) ) : '';
		$man_id      = get_post_meta( $project_id, 'voidempo_project_manager', true );

		$member_status = array_fill( 0, count( $member_ids ), $task_status );

		$imp_user   = implode( ',', $member_ids );
		$imp_status = implode( ',', $member_status );

		$task_title       = isset( $_POST['task_title'] ) ? sanitize_text_field( wp_unslash( $_POST['task_title'] ) ) : '';
		$task_description = isset( $_POST['task_description'] ) ? sanitize_textarea_field( wp_unslash( $_POST['task_description'] ) ) : '';

		$estimated_hours = '';
		if ( ! empty( $_POST['task_estimated_hours'] ) && ! empty( $_POST['voidempo_task_estimated_min'] ) ) {
			$task_hours      = sanitize_text_field( wp_unslash( $_POST['task_estimated_hours'] ) );
			$task_minutes    = sanitize_text_field( wp_unslash( $_POST['voidempo_task_estimated_min'] ) );
			$estimated_hours = $task_hours . ':' . $task_minutes;
		}

		$date_created = gmdate( 'Y-m-d H:i:s' );

		$wpdb->insert(
			"{$wpdb->prefix}voidempo_task",
			array(
				'project_id'       => $project_id,
				'user_id'          => $imp_user,
				'manager_id'       => $man_id,
				'task_title'       => $task_title,
				'task_description' => $task_description,
				'status'           => $task_status,
				'members_status'   => $imp_status,
				'estimated_hours'  => $estimated_hours,
				'date_created'     => $date_created,
				'is_delete'        => 0,
			),
			array( '%d', '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%d' )
		);

		$task_id = $wpdb->insert_id;

		$user_names = array();
		foreach ( $member_ids as $uid ) {
			$user_names[] = voidempo_user_by_id_( $uid );
		}
		$usersname = implode( ',', $user_names );

		$task_log_desc = "Task $task_title created. Members assigned $usersname. Task Description is $task_description. Task Status is $task_status. Estimated hours set to $estimated_hours.";

		$wpdb->insert(
			"{$wpdb->prefix}voidempo_task_log",
			array(
				'user_id'      => get_current_user_id(),
				'description'  => sanitize_text_field( $task_log_desc ),
				'object_id'    => intval( $task_id ),
				'date_created' => current_time( 'mysql' ),
			),
			array( '%d', '%s', '%d', '%s' )
		);

		if ( ! empty( $task_id ) ) {
			echo 'task_created';
		}
		wp_die();
	}
	/**
	 * Retrieves EOD (End of Day) report data filtered by a specific date.
	 *
	 * This method fetches EOD entries from the database based on a given date,
	 * and optionally by user or project, for reporting or display purposes.
	 *
	 * @return array Array of EOD records matching the filter.
	 */
	public function voidempo_get_eods_databydate() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_safe_redirect( wp_login_url() );
			exit;
		}
		
		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) || current_user_can( 'voidempo_employee_access' )) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		global $wpdb;
		$date_selectchange = isset( $_POST['date'] ) ? sanitize_textarea_field( wp_unslash( $_POST['date'] ) ) : '';

		include VOIDEMPO_PLUGIN_PATH . '/templates/create-eodin.php';
		wp_die();
	}

	/**
	 * Inserts End of Day (EOD) report data into the database.
	 *
	 * This method handles the creation of a new EOD entry, including details such as
	 * the reporting user, date, task summary, hours worked, and any additional notes.
	 *
	 * @return void
	 */
	public function voidempo_insert_eod_data() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );
		if ( ! is_user_logged_in() ) {
			wp_safe_redirect( wp_login_url() );
			exit;
		}
		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) || current_user_can( 'voidempo_employee_access' )) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}
		global $wpdb;

		$eod_data_raw = filter_input( INPUT_POST, 'eodData', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
		$eod_data     = is_array( $eod_data_raw ) ? $eod_data_raw : array();
		$eod_date_raw = filter_input( INPUT_POST, 'eod_date', FILTER_SANITIZE_STRING );
		$eod_date     = ( ! empty( $eod_date_raw ) && strtotime( $eod_date_raw ) !== false )
			? gmdate( 'Y-m-d', strtotime( $eod_date_raw ) )
			: current_time( 'Y-m-d' );

		$user_id            = get_current_user_id();
		$date_time          = current_time( 'mysql' );
		$current_time_utc   = current_time( 'mysql', true );
		$current_time_local = get_date_from_gmt( $current_time_utc, 'H:i:s' );

		$entries = array();

		foreach ( $eod_data as $project_id => $tasks ) {
			$project_id = absint( $project_id );
			if ( ! $project_id || ! is_array( $tasks ) ) {
				continue;
			}
			$project_exists = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT COUNT(*) FROM {$wpdb->prefix}voidempo_projects WHERE related_post_id = %d",
					$project_id
				)
			);
			foreach ( $tasks as $task_id => $data ) {
				$task_id = absint( $task_id );
				if ( ! $task_id || ! is_array( $data ) ) {
					continue;
				}
				$task_exists = $wpdb->get_var(
					$wpdb->prepare(
						"SELECT COUNT(*) FROM {$wpdb->prefix}voidempo_task WHERE id = %d",
						$task_id
					)
				);

				if ( ! $project_exists || ! $task_exists ) {
					continue;
				}

				$eod_hours_raw     = isset( $data['eod_hours'] ) ? $data['eod_hours'] : '';
				$eod_notes_raw     = isset( $data['eod_notes'] ) ? $data['eod_notes'] : '';
				$mark_complete_raw = isset( $data['mark_as_complete'] ) ? $data['mark_as_complete'] : '';

				$eod_hours           = sanitize_text_field( $eod_hours_raw );
				$eod_notes           = sanitize_textarea_field( $eod_notes_raw );
				$eod_markas_complete = ( $mark_complete_raw === 'on' ) ? 'Completed' : 'Inprogress';

				if ( empty( $eod_hours ) && empty( $eod_notes ) ) {
					continue;
				}

				$status              = $eod_markas_complete;
				$completion_datetime = ( $status === 'Completed' ) ? "$eod_date $current_time_local" : '';

				$entries[] = array(
					'project_id'   => $project_id,
					'task_id'      => $task_id,
					'user_id'      => $user_id,
					'hours'        => $eod_hours,
					'notes'        => $eod_notes,
					'status'       => $status,
					'date_created' => $eod_date,
					'entry_date'   => $date_time,
				);
			}
		}

		if ( ! empty( $entries ) ) {
			foreach ( $entries as $entry ) {
				$inserted = $wpdb->insert(
					$wpdb->prefix . 'voidempo_eod',
					$entry,
					array( '%d', '%d', '%d', '%s', '%s', '%s', '%s', '%s' )
				);

				if ( $entry['status'] === 'Completed' ) {
					$complete_date = "{$entry['date_created']} " . current_time( 'H:i:s' );
				} else {
					$complete_date = null;
				}

				if ( $inserted ) {
					$updated = $wpdb->update(
						$wpdb->prefix . 'voidempo_task',
						array(
							'status'        => $entry['status'],
							'complete_date' => $complete_date,
						),
						array( 'id' => $entry['task_id'] ),
						array( '%s', '%s' ),
						array( '%d' )
					);

					if ( $updated !== false ) {
						wp_cache_delete( 'voidempo_task_' . $entry['task_id'], 'voidempo_tasks' );
					}

					$description = "EOD submitted for Task ID {$entry['task_id']} with status: {$entry['status']}";

					$wpdb->insert(
						$wpdb->prefix . 'voidempo_task_log',
						array(
							'user_id'      => $user_id,
							'description'  => $description,
							'object_id'    => $entry['task_id'],
							'date_created' => $date_time,
						),
						array( '%d', '%s', '%d', '%s' )
					);

					$log_description = "EOD submitted for Task ID {$entry['task_id']} with hours:{$entry['hours']} notes:{$entry['notes']} status: {$entry['status']}";

					$wpdb->insert(
						$wpdb->prefix . 'voidempo_eod_log',
						array(
							'user_id'      => $user_id,
							'description'  => $log_description,
							'object_id'    => $entry['task_id'],
							'date_created' => $date_time,
						),
						array( '%d', '%s', '%d', '%s' )
					);
				}
			}

			wp_send_json_success( array( 'message' => 'EOD submitted successfully!' ) );
		} else {
			wp_send_json_error( array( 'message' => 'Please enter EOD details before submitting.' ) );
		}
	}
	/**
	 * This function fetches tasks related to a given project ID, including details
	 * like task name, status, assigned user, and due date.
	 *
	 * @param int $project_id The ID of the project to retrieve tasks for.
	 * @return array Array of task data related to the project.
	 */
	public function voidempo_get_tasks_by_project() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );
		if ( ! is_user_logged_in() ) {
			wp_safe_redirect( wp_login_url() );
			exit;
		}
		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) || current_user_can( 'voidempo_employee_access' )) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}
		global $wpdb;
		$project_id = isset( $_POST['project_id'] ) ? intval( $_POST['project_id'] ) : 0;
		$user_id    = get_current_user_id();

		if ( current_user_can( 'voidempo_manager_access' ) || current_user_can( 'manage_options' ) ) {
			$cache_key = 'tasks_for_project_' . $project_id;
			$tasks     = wp_cache_get( $cache_key );

			if ( false === $tasks ) {
				$tasks = $wpdb->get_results(
					$wpdb->prepare(
						"SELECT id, task_title FROM {$wpdb->prefix}voidempo_task WHERE project_id = %d",
						$project_id
					)
				);
				wp_cache_set( $cache_key, $tasks, '', 600 );
			}
		} else {
			$cache_key = 'tasks_for_project_' . $project_id . '_user_' . $user_id;
			$tasks     = wp_cache_get( $cache_key );

			if ( false === $tasks ) {
				$tasks = $wpdb->get_results(
					$wpdb->prepare(
						"SELECT id, task_title FROM {$wpdb->prefix}voidempo_task WHERE project_id = %d AND user_id = %d",
						$project_id,
						$user_id
					)
				);
				wp_cache_set( $cache_key, $tasks, '', 600 );
			}
		}
		usort(
			$tasks,
			function ( $a, $b ) {
				return strcasecmp( $a->task_title, $b->task_title );
			}
		);
		$options = '<option value="">' . esc_html__( 'Select Task', 'voidek-employee-portal' ) . '</option>';

		foreach ( $tasks as $task ) {
			$options .= sprintf(
				'<option value="%s">%s</option>',
				esc_attr( $task->id ),
				esc_html( $task->task_title )
			);
		}

		$allowed_html = array(
			'option' => array(
				'value' => true,
			),
		);

		echo wp_kses( $options, $allowed_html );
		wp_die();
	}

	/**
	 * Retrieves all projects from the database.
	 *
	 * This method fetches a list of all projects, possibly including their
	 * titles, statuses, assigned users, and metadata.
	 *
	 * @return array Array of project data.
	 */
	public function voidempo_fetch_all_projects() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		// if ( ! is_user_logged_in() ) {
		// 	wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
		// 	wp_die();
		// }
		// if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
		// 	wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		// }

		global $wpdb;

		$draw               = isset( $_POST['draw'] ) ? intval( $_POST['draw'] ) : 1;
		$start              = isset( $_POST['start'] ) ? intval( $_POST['start'] ) : 0;
		$length             = isset( $_POST['length'] ) ? intval( $_POST['length'] ) : 10;
		$search_value       = isset( $_POST['search']['value'] ) ? sanitize_text_field( wp_unslash( $_POST['search']['value'] ) ) : '';
		$order_column_index = isset( $_POST['order'][0]['column'] ) ? intval( $_POST['order'][0]['column'] ) : 0;
		$order_dir          = isset( $_POST['order'][0]['dir'] ) && in_array( strtolower( sanitize_text_field( wp_unslash( $_POST['order'][0]['dir'] ) ) ), array( 'asc', 'desc' ), true )
								? strtolower( sanitize_text_field( wp_unslash( $_POST['order'][0]['dir'] ) ) )
								: 'asc';

		$columns            = array( 'project_title', 'start_date', 'end_date', 'manager_id', 'member_id', 'status' );
		$allowed_columns    = $columns;
		$order_by           = isset( $allowed_columns[ $order_column_index ] ) ? $allowed_columns[ $order_column_index ] : 'id';
		$allowed_directions = array( 'asc', 'desc' );
		$order_dir          = in_array( $order_dir, $allowed_directions, true ) ? $order_dir : 'asc';

		// --- WHERE building ---
		$where_clauses = array();
		$params        = array();

		if ( ! empty( $search_value ) ) {
			$like = '%' . $wpdb->esc_like( $search_value ) . '%';

			// Cache matching user IDs
			$cache_key         = 'matching_user_ids_' . md5( $like );
			$matching_user_ids = wp_cache_get( $cache_key );

			if ( false === $matching_user_ids ) {
				$matching_user_ids = $wpdb->get_col(
					$wpdb->prepare(
						"SELECT ID FROM {$wpdb->prefix}users WHERE display_name LIKE %s",
						$like
					)
				);
				wp_cache_set( $cache_key, $matching_user_ids, '', 600 );
			}

			$or_clauses = array();

			$or_clauses[] = 'project_title LIKE %s';
			$params[]     = $like;

			$or_clauses[] = 'status LIKE %s';
			$params[]     = $like;

			if ( ! empty( $matching_user_ids ) ) {
				$placeholders = implode( ',', array_fill( 0, count( $matching_user_ids ), '%d' ) );
				$or_clauses[] = "manager_id IN ($placeholders)";
				$params       = array_merge( $params, $matching_user_ids );

				foreach ( $matching_user_ids as $uid ) {
					$or_clauses[] = 'FIND_IN_SET(%d, member_id)';
					$params[]     = $uid;
				}
			}

			$where_clauses[] = '(' . implode( ' OR ', $or_clauses ) . ')';
		}

		$where_sql = '';
		if ( ! empty( $where_clauses ) ) {
			$where_sql = 'WHERE ' . implode( ' AND ', $where_clauses );
		}

		$total_records = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}voidempo_projects {$where_sql}", ...$params ) );

		// --- Data query ---

		$data_params = array_merge( $params, array( $length, $start ) );

		$projects = $wpdb->get_results(
			$wpdb->prepare( "SELECT * FROM {$wpdb->prefix}voidempo_projects {$where_sql} ORDER BY {$order_by} {$order_dir} LIMIT %d OFFSET %d", ...$data_params ),
			ARRAY_A
		);

		$data = array();
		foreach ( $projects as $project ) {
			$manager_id   = $project['manager_id'];
			$cache_key    = 'manager_name_' . $manager_id;
			$manager_name = wp_cache_get( $cache_key );

			if ( $manager_name === false ) {
				$manager_name = $wpdb->get_var(
					$wpdb->prepare( "SELECT display_name FROM {$wpdb->prefix}users WHERE ID = %d", $manager_id )
				);
				wp_cache_set( $cache_key, $manager_name, '', 3600 );
			}

			$member_ids = explode( ',', $project['member_id'] );
			if ( ! empty( $member_ids ) ) {

				$placeholders = implode( ',', array_fill( 0, count( $member_ids ), '%d' ) );
				$cache_key    = 'member_names_' . md5( implode( ',', $member_ids ) );
				$member_names = wp_cache_get( $cache_key );

				if ( $member_names === false ) {
					$member_names = $wpdb->get_col(
						$wpdb->prepare(
							"SELECT display_name FROM {$wpdb->prefix}users WHERE ID IN ($placeholders)",
							...array_map( 'intval', $member_ids )
						)
					);
					wp_cache_set( $cache_key, $member_names, '', 3600 );
				}

				$member_names_str = implode( ', ', $member_names );
			} else {
				$member_names_str = '';
			}

			$data[] = array(
				$project['project_title'],
				$project['start_date'],
				$project['end_date'],
				$manager_name,
				$member_names_str,
				$project['status'],
				'<button class="btn btn-primary btn-sm edit-project" data-id="' . $project['id'] . '">Edit</button>
                 <button class="btn btn-danger btn-sm delete-project" data-id="' . $project['id'] . '">Delete</button>',
			);
		}

		wp_send_json(
			array(
				'draw'            => $draw,
				'recordsTotal'    => $total_records,
				'recordsFiltered' => $total_records,
				'data'            => $data,
			)
		);
	}

	/**
	 * Retrieves details of a single project.
	 *
	 * This method fetches information about a specific project,
	 * typically by its ID, including title, description, dates, status, and members.
	 *
	 * @return array|WP_Post|null Project data as an array or WP_Post object, or null if not found.
	 */
	public function voidempo_get_single_project() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}
		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		$id = isset( $_POST['project_id'] ) ? intval( $_POST['project_id'] ) : 0;

		global $wpdb;
		$table     = $wpdb->prefix . 'voidempo_projects';
		$cache_key = 'project_' . $id;
		$project   = wp_cache_get( $cache_key );

		if ( false === $project ) {
			$project = $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM `{$wpdb->prefix}voidempo_projects` WHERE id = %d",
					$id
				),
				ARRAY_A
			);
			wp_cache_set( $cache_key, $project );
		}

		if ( ! $project ) {
			wp_send_json_error( array( 'message' => 'Project not found' ) );
		}

		$users_table = $wpdb->prefix . 'users';
		$cache_key   = 'all_users_id_display_name';
		$users       = wp_cache_get( $cache_key );

		if ( false === $users ) {
			$users = $wpdb->get_results(
				$wpdb->prepare( "SELECT ID, display_name FROM {$wpdb->users} WHERE 1 = %d", 1 )
			);

			wp_cache_set( $cache_key, $users );
		}

		$managers_dropdown = '';
		$members_dropdown  = '';
		foreach ( $users as $user ) {
			$selected_m         = ( $user->ID === $project['manager_id'] ) ? 'selected' : '';
			$managers_dropdown .= "<option value='{$user->ID}' $selected_m>{$user->display_name}</option>";

			$selected_member   = in_array( $user->ID, explode( ',', $project['member_id'] ) ) ? 'selected' : '';
			$members_dropdown .= "<option value='{$user->ID}' $selected_member>{$user->display_name}</option>";
		}

		wp_send_json_success(
			array(
				'id'                => $project['id'],
				'project_title'     => $project['project_title'],
				'start_date'        => $project['start_date'],
				'end_date'          => $project['end_date'],
				'status'            => $project['status'],
				'managers_dropdown' => $managers_dropdown,
				'members_dropdown'  => $members_dropdown,
			)
		);
	}

	/**
	 * Updates a project's details.
	 *
	 * This method updates project information such as title, description,
	 * status, assigned members, start/end dates, and any custom metadata.
	 *
	 * @return void
	 */
	public function voidempo_update_project() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		$data = array();

		$raw_data = filter_input( INPUT_POST, 'data', FILTER_SANITIZE_STRING );
		$data     = array();

		if ( $raw_data ) {
			parse_str( $raw_data, $data );
		}

		global $wpdb;
		$project_id = intval( $data['project_id'] );

			$cache_key = 'related_post_id_' . $project_id;
			$post_id   = wp_cache_get( $cache_key );

		if ( false === $post_id ) {
			$post_id = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT related_post_id FROM {$wpdb->prefix}voidempo_projects WHERE id = %d",
					$project_id
				)
			);
			wp_cache_set( $cache_key, $post_id );
		}

		if ( $post_id && get_post( $post_id ) ) {
			$updated_post = array(
				'ID'           => $post_id,
				'post_title'   => sanitize_text_field( $data['project_title'] ),
				'post_content' => sanitize_textarea_field( $data['project_description'] ),
			);
			wp_update_post( $updated_post );
		}

		$table_name = $wpdb->prefix . 'voidempo_projects';
		$result     = $wpdb->update(
			$table_name,
			array(
				'project_title' => sanitize_text_field( $data['project_title'] ),
				'start_date'    => sanitize_text_field( $data['start_date'] ),
				'end_date'      => sanitize_text_field( $data['end_date'] ),
				'status'        => sanitize_text_field( $data['status'] ),
				'manager_id'    => intval( $data['manager_id'] ),
				'member_id'     => implode( ',', array_map( 'intval', $data['member_id'] ) ),
			),
			array( 'id' => $project_id ),
			array( '%s', '%s', '%s', '%s', '%d', '%s' ),
			array( '%d' )
		);
		if ( false !== $result ) {
			wp_cache_delete( 'voidempo_project_' . $project_id );
		}
		if ( $post_id ) {
			if ( ! empty( $data['start_date'] ) ) {
				update_post_meta( $post_id, 'voidempo_project_start_date', sanitize_text_field( $data['start_date'] ) );
			}

			if ( ! empty( $data['end_date'] ) ) {
				update_post_meta( $post_id, 'voidempo_project_end_date', sanitize_text_field( $data['end_date'] ) );
			}

			if ( ! empty( $data['manager_id'] ) ) {
				update_post_meta( $post_id, 'voidempo_project_manager', sanitize_text_field( $data['manager_id'] ) );
			}

			if ( ! empty( $data['member_id'] ) ) {
				$sanitized_member_ids = array_map( 'sanitize_text_field', $data['member_id'] );
				update_post_meta( $post_id, 'voidempo_project_members', implode( ',', $sanitized_member_ids ) );
			}

			if ( ! empty( $data['status'] ) ) {
				update_post_meta( $post_id, 'voidempo_project_status', sanitize_text_field( $data['status'] ) );
			}
		}

		if ( false !== $result ) {
			wp_send_json_success( array( 'message' => 'Project updated successfully.' ) );
		} else {
			wp_send_json_error( array( 'message' => 'Failed to update project.' ) );
		}

		wp_die();
	}

	/**
	 * Deletes a project and its related data.
	 *
	 * This method handles the removal of a project record from the database,
	 * including any associated metadata, tasks, or custom fields.
	 *
	 * @return void
	 */
	public function voidempo_delete_project() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}
		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		$project_id = isset( $_POST['project_id'] ) ? intval( $_POST['project_id'] ) : 0;
		global $wpdb;
		$table = $wpdb->prefix . 'voidempo_projects';

		$deleted = $wpdb->delete( $table, array( 'id' => $project_id ) );
		if ( $deleted !== false ) {
			wp_cache_delete( 'voidempo_project_' . $project_id );
		}

		if ( $deleted ) {
			wp_send_json_success( array( 'message' => 'Project deleted successfully.' ) );
		} else {
			wp_send_json_error( array( 'message' => 'Project deletion failed or not found.' ) );
		}
	}

	/**
	 * Handles user registration logic.
	 *
	 * @return void
	 */
	public function voidempo_user_registration() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
				wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
				wp_die();
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}
			
		$data          = array();
		$form_data_raw = filter_input( INPUT_POST, 'form_data', FILTER_SANITIZE_STRING );
		if ( $form_data_raw ) {
			parse_str( $form_data_raw, $data );
			$data = array_map( 'sanitize_text_field', $data );
		}

		$username        = sanitize_user( $data['username'] );
		$email           = sanitize_email( $data['email'] );
		$password        = sanitize_text_field( $data['password'] );
		$first_name      = sanitize_text_field( $data['first_name'] );
		$last_name       = sanitize_text_field( $data['last_name'] );
		$dob             = sanitize_text_field( $data['user_dob'] );
		$joining_date    = sanitize_text_field( $data['user_joining_date'] );
		
		if ( username_exists( $username ) ) {
			wp_send_json(
				array(
					'success' => false,
					'message' => '<div style="color:red;">Username already exists.</div>',
				)
			);
		}

		if ( email_exists( $email ) ) {
			wp_send_json(
				array(
					'success' => false,
					'message' => '<div style="color:red;">Email already exists.</div>',
				)
			);
		}

		$user_id = wp_insert_user(
			array(
				'user_login' => $username,
				'user_pass'  => $password,
				'user_email' => $email,
				'first_name' => $first_name,
				'last_name'  => $last_name,
				'role'       => 'subscriber',
			)
		);

		if ( is_wp_error( $user_id ) ) {
			wp_send_json(
				array(
					'success' => false,
					'message' => '<div style="color:red;">' . $user_id->get_error_message() . '</div>',
				)
			);
		}

		update_user_meta( $user_id, 'user_dob', $dob );
		update_user_meta( $user_id, 'user_joining_date', $joining_date );

		do_action( 'voidempo_user_registration', $user_id, $data );
		wp_send_json(
			array(
				'success' => true,
				'message' => '<div style="color:green;">User registered successfully!</div>',
			)
		);
	}

	/**
	 * Fetches data for the currently logged-in user.
	 *
	 * @return void
	 */
	public function voidempo_fetch_user_data() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}
		
		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		$draw         = isset( $_POST['draw'] ) ? intval( $_POST['draw'] ) : 1;
		$search_value = isset( $_POST['search']['value'] ) ? sanitize_text_field( wp_unslash( $_POST['search']['value'] ) ) : '';

		$users = get_users( array(
			'role__in' => array( 'subscriber', 'manager' ),
			'number'   => -1,
		) );

		$data = array();

		foreach ( $users as $user ) {
			$user_id   = $user->ID;
			$full_name = trim( get_user_meta( $user_id, 'first_name', true ) . ' ' . get_user_meta( $user_id, 'last_name', true ) );
			$email     = $user->user_email;

			if ( $search_value && stripos( $full_name, $search_value ) === false && stripos( $email, $search_value ) === false ) {
				continue;
			}

			// Basic row
			$row = array(
				'name'      => esc_html( $full_name ),
				'email'     => esc_html( $email ),
				'dob'       => esc_html( get_user_meta( $user_id, 'user_dob', true ) ),
				'joining'   => esc_html( get_user_meta( $user_id, 'user_joining_date', true ) ),
				'actions'                   => '<button class="btn btn-primary btn-sm edit-user reg_edit" data-id="' . esc_attr( $user_id ) . '">Edit</button> ' .
											'<button class="btn btn-danger btn-sm delete-user reg_delete" data-id="' . esc_attr( $user_id ) . '">Delete</button>',
				'id' => $user_id,
			);

			// **Action hook for pro plugin to modify row**
		    do_action_ref_array( 'voidempo_pro_user_row', array( &$row, $user_id ) );
			$data[] = $row;
		}

		wp_send_json( array(
			'draw'            => $draw,
			'recordsTotal'    => count( $data ),
			'recordsFiltered' => count( $data ),
			'data'            => $data,
		) );
	}



	/**
	 * Retrieves user details.
	 *
	 * This method fetches and returns information about a specific user.
	 *
	 * @return void
	 */
	public function voidempo_get_user_details() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		$user_id = isset( $_POST['user_id'] ) ? intval( $_POST['user_id'] ) : 0;
		$user    = get_user_by( 'ID', $user_id );
		$first_name = get_user_meta( $user_id, 'first_name', true );
		$last_name  = get_user_meta( $user_id, 'last_name', true );
		if ( $user ) {

			$disabled = get_user_meta( $user_id, '_employee_disabled', true );

			$response = array(
				'name' => trim($first_name . ' ' . $last_name),
				'dob'                 => get_user_meta( $user_id, 'user_dob', true ),
				'joining'             => get_user_meta( $user_id, 'user_joining_date', true ),
				'disabled'            => (int) $disabled,
			);

			$response = apply_filters( 'voidempo_get_user_details_response', $response, $user_id );

			wp_send_json_success( $response );

		} else {
			wp_send_json_error();
		}
	}


	/**
	 * Updates the details of a user.
	 *
	 * This method updates user-related data such as name, email, role, or any custom metadata.
	 * It is typically triggered via a form submission or an internal process.
	 *
	 * @return void
	 */
	public function voidempo_update_user_details() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );
		

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		$user_id = 0;

		if ( isset( $_POST['user_id'] ) ) {
			$user_id = intval( sanitize_text_field( wp_unslash( $_POST['user_id'] ) ) );
		}
		if ( isset( $_POST['dob'] ) ) {
			update_user_meta( $user_id, 'user_dob', sanitize_text_field( wp_unslash( $_POST['dob'] ) ) );
		}
		if ( isset( $_POST['joining'] ) ) {
			update_user_meta( $user_id, 'user_joining_date', sanitize_text_field( wp_unslash( $_POST['joining'] ) ) );
		}
		
		$status  = isset( $_POST['employee_status'] ) ? sanitize_text_field( wp_unslash( $_POST['employee_status'] ) ) : 'active';
		$user_id = intval( $_POST['user_id'] );
		if ( $status === 'deactive' ) {
			update_user_meta( $user_id, '_employee_disabled', 1 );
		} else {
			update_user_meta( $user_id, '_employee_disabled', 0 );
		}

		do_action( 'voidempo_update_user_leave_details', $user_id, $_POST );

		wp_send_json_success( array( 'message' => 'User data updated' ) );
	}

	/**
	 * Deletes a user's details from the system.
	 *
	 * This method handles the deletion of user-related data such as profile info,
	 * metadata, or custom plugin records. Typically used by admins or via an internal action.
	 *
	 * @return void
	 */
	public function voidempo_delete_user_details() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}
		if ( ! current_user_can( 'delete_users' ) ) {
			wp_send_json_error( [ 'message' => 'You cannot delete users.' ], 403 );
			wp_die();
    	}
 		if ( get_current_user_id() == $user_id ) {
			wp_send_json_error( [ 'message' => 'You cannot delete your own account.' ], 403 );
			wp_die();
		}
		 
		$user_id = isset( $_POST['user_id'] ) ? intval( $_POST['user_id'] ) : 0;
		if ( $user_id ) {
			delete_user_meta( $user_id, 'user_dob' );
			delete_user_meta( $user_id, 'user_joining_date' );			
			do_action( 'voidempo_delete_user_details', $user_id);
			wp_delete_user( $user_id );
			wp_send_json_success( array( 'message' => 'User details deleted.' ) );
		} else {
			wp_send_json_error( array( 'message' => 'Invalid user ID.' ) );
		}
	}

	/**
	 * Retrieves tasks associated with a specific project.
	 *
	 * This function is used to fetch all tasks linked to a project,
	 * typically for display in dashboards, reports, or detailed views.
	 *
	 * @return void
	 */
	public function voidempo_get_project_tasks() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		

		global $wpdb;

		$project_id = isset( $_POST['project_id'] ) ? intval( $_POST['project_id'] ) : 0;
		
		$cache_key = 'voidempo_task_project_' . $project_id;
		$tasks     = wp_cache_get( $cache_key );

		if ( false === $tasks ) {
			$tasks = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT id, task_title FROM {$wpdb->prefix}voidempo_task WHERE project_id = %d",
					$project_id
				)
			);
			wp_cache_set( $cache_key, $tasks );
		}

		usort(
			$tasks,
			function ( $a, $b ) {
				return strcasecmp( $a->task_title, $b->task_title );
			}
		);

		$options = '<option value="0">--Select Task--</option>';
		foreach ( $tasks as $task ) {
			$options .= '<option value="' . esc_attr( $task->task_title ) . '">' . esc_html( $task->task_title ) . '</option>';
		}
		echo wp_kses( $options, array( 'option' => array( 'value' => true ) ) );

		wp_die();
	}

		/**
		 * AJAX handler to delete an EOD (End of Day) report entry.
		 *
		 * Expects the EOD entry ID via POST and removes the corresponding post or record.
		 * Sends a JSON success or error response back to the client.
		 *
		 * @return void Outputs JSON response and exits.
		 */
	public function voidempo_delete_eod() {

		check_ajax_referer( 'voidempo_dashboard_nonce', 'security' );
		
		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}


		global $wpdb;

		$eod_id = ! empty( $_POST['eod_id'] ) ? sanitize_text_field( wp_unslash( $_POST['eod_id'] ) ) : '';

		$deleted = $wpdb->update( $wpdb->prefix . 'voidempo_eod', array( 'is_delete' => '1' ), array( 'id' => $eod_id ) );
		if ( $deleted !== false ) {
			wp_cache_delete( 'voidempo_eod_' . $eod_id );
		}
		if ( $deleted == '1' ) {
			$project_id = ! empty( $_POST['project_id'] ) ? absint( $_POST['project_id'] ) : 0;
			$task_id    = ! empty( $_POST['task_id'] ) ? sanitize_text_field( wp_unslash( $_POST['task_id'] ) ) : '';
			$user_id    = ! empty( $_POST['user_id'] ) ? sanitize_text_field( wp_unslash( $_POST['user_id'] ) ) : '';

			$get_task_data = voidempo_fetch_tasksby_taskid( $task_id );
			$members_id    = explode( ',', $get_task_data[0]->user_id );

			$members_status_old = explode( ',', $get_task_data[0]->members_status );

			$members_status_combine = array_combine( $members_id, $members_status_old );

			$is_manager                   = voidempo_fn_check_is_manager_( $project_id, $user_id );
			$eod_markas_compelete_members = '';

			if (
				isset( $_POST['voidempo_task_mac_members'] ) &&
				isset( $_POST['voidempo_task_mac_members'][ $project_id ] ) &&
				isset( $_POST['voidempo_task_mac_members'][ $project_id ][ $task_id ] ) &&
				isset( $_POST['voidempo_task_mac_members'][ $project_id ][ $task_id ]['mark_as_complete'] )
			) {
				$eod_markas_compelete_members = sanitize_text_field(
					wp_unslash(
						$_POST['voidempo_task_mac_members'][ $project_id ][ $task_id ]['mark_as_complete']
					)
				);
			}
			// Update member status to 'Inprogress' (non-manager logic).
			if ( $is_manager == 'is_not' ) {
				$members_status_combine[ $user_id ] = 'Inprogress';
			}

			// Update member status to 'Inprogress' (manager logic).
			foreach ( $members_id as $member_id ) {
				if ( $is_manager == 'is_manager' ) {

					$members_status_combine[ $member_id ] = 'Inprogress';
				}
			}

			$members_status = implode( ',', $members_status_combine );
			$wpdb->update(
				$wpdb->prefix . 'voidempo_task',
				array(
					'status'         => 'Inprogress',
					'members_status' => $members_status,
				),
				array( 'id' => $task_id )
			);

			$current_user_id = absint( get_current_user_id() );

			$log_inserted_task = $wpdb->insert(
				$wpdb->prefix . 'voidempo_tasks_log',
				array(
					'user_id'      => $current_user_id,
					'description'  => 'task_id id ' . $task_id . ' status changed from Completed to Inprogress and members_status changed from "' . $members_status_old . '" to "' . $members_status . '"',
					'object_id'    => $eod_id,
					'date_created' => gmdate( 'Y-m-d H:i:s' ),
				)
			);
			$wpdb->insert(
				$wpdb->prefix . 'voidempo_eod_log',
				array(
					'user_id'      => $current_user_id,
					'description'  => 'EOD id ' . $eod_id . ' is deleted',
					'object_id'    => $eod_id,
					'date_created' => gmdate( 'Y-m-d H:i:s' ),
				)
			);

			echo 'Deleted';
		}

		wp_die();
	}

	/**
	 * AJAX callback to fetch task details.
	 *
	 * This method is typically triggered via a JavaScript AJAX request
	 * and returns detailed information about a specific task.
	 *
	 * @return void Outputs JSON response and exits.
	 */
	public function voidempo_get_task_details_callback() {

		check_ajax_referer( 'manager_ajax_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}

		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		global $wpdb;

		$task_id = isset( $_POST['task_id'] ) ? intval( $_POST['task_id'] ) : 0;

		if ( ! $task_id ) {
			wp_send_json_error( 'Invalid Task ID' );
			return;
		}
		$cache_key   = 'task_data_' . absint( $task_id );
		$cache_group = 'voidempo_task';

		$task_data = wp_cache_get( $cache_key, $cache_group );

		if ( false === $task_data ) {
			$task_data = $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}voidempo_task WHERE id = %d",
					$task_id
				)
			);
			if ( $task_data ) {
				wp_cache_set( $cache_key, $task_data, $cache_group, HOUR_IN_SECONDS );
			}
		}
		if ( empty( $task_data ) ) {
			wp_send_json_error( 'Task not found' );
			return;
		}

		$project_id = intval( $task_data->project_id );

		$project_managers = get_post_meta( $project_id, 'voidempo_project_manager', true );
		$project_members  = get_post_meta( $project_id, 'voidempo_project_members', true );

		$project_managers = ! empty( $project_managers ) ? array_map( 'trim', explode( ',', $project_managers ) ) : array();
		$project_members  = ! empty( $project_members ) ? array_map( 'trim', explode( ',', $project_members ) ) : array();

		$all_project_users = array_unique( array_merge( $project_managers, $project_members ) );
		$all_project_users = array_map( 'intval', array_filter( $all_project_users ) );

		$assigned_member_ids = ! empty( $task_data->user_id )
			? array_map( 'intval', explode( ',', $task_data->user_id ) )
			: array();

		$assigned_member_names = array();
		foreach ( $assigned_member_ids as $member_id ) {
			$user = get_user_by( 'id', $member_id );
			if ( $user && get_user_meta( $user->ID, '_employee_disabled', true ) != 1 ) {
				$assigned_member_names[] = $user->display_name;
			}
		}

		$manager_id        = intval( $task_data->manager_id );
		$managers_dropdown = '';
		$members_dropdown  = '';

		foreach ( $all_project_users as $user_id ) {
			$user_data = get_user_by( 'id', $user_id );
			if ( $user_data && get_user_meta( $user_data->ID, '_employee_disabled', true ) != 1 ) {
				$selected_manager   = ( $user_data->ID === $manager_id ) ? 'selected' : '';
				$managers_dropdown .= "<option value='{$user_data->ID}' {$selected_manager}>{$user_data->display_name}</option>";

				$selected_member   = in_array( $user_data->ID, $assigned_member_ids ) ? 'selected' : '';
				$members_dropdown .= "<option value='{$user_data->ID}' {$selected_member}>{$user_data->display_name}</option>";
			}
		}

		$hours   = 0;
		$minutes = 0;
		if ( ! empty( $task_data->estimated_hours ) && strpos( $task_data->estimated_hours, ':' ) !== false ) {
			list($hours, $minutes) = explode( ':', $task_data->estimated_hours );
			$hours                 = intval( $hours );
			$minutes               = intval( $minutes );
		}

		wp_send_json_success(
			array(
				'id'                    => intval( $task_data->id ),
				'title'                 => sanitize_text_field( $task_data->task_title ),
				'description'           => sanitize_textarea_field( $task_data->task_description ),
				'status'                => sanitize_text_field( $task_data->status ),
				'manager'               => $manager_id,
				'managers_dropdown'     => $managers_dropdown,
				'assigned_member_names' => $assigned_member_names,
				'members'               => $assigned_member_ids,
				'members_dropdown'      => $members_dropdown,
				'estimated_hours'       => $hours,
				'estimated_minutes'     => $minutes,
			)
		);
	}

	/**
	 * Retrieves End of Day (EOD) report data for the current user or filtered criteria.
	 *
	 * This method fetches and returns EOD entries from the database.
	 * Can be used for reporting, performance tracking, or dashboard views.
	 *
	 * @return array Array of EOD data records.
	 */
	public function voidempo_get_eod_data() {

		check_ajax_referer( 'manager_ajax_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}

		if (! current_user_can( 'manage_options' ) && ! current_user_can( 'voidempo_manager_access' ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		global $wpdb;

		// Ensure eod_id is provided.
		if ( ! isset( $_POST['eod_id'] ) || empty( $_POST['eod_id'] ) ) {
			wp_send_json_error( 'EOD ID is required.' );
		}

		$eod_id    = isset( $_POST['eod_id'] ) ? intval( $_POST['eod_id'] ) : 0;
		$cache_key = 'voidempo_eod_' . $eod_id;
		$eod_data  = wp_cache_get( $cache_key );

		if ( false === $eod_data ) {
			$eod_data = $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}voidempo_eod WHERE id = %d",
					$eod_id
				)
			);
			wp_cache_set( $cache_key, $eod_data );
		}

		if ( $eod_data ) {
			$project_title = get_post( $eod_data->project_id )->post_title;
			$task_data     = voidempo_fetch_tasksby_taskid( $eod_data->task_id );
			$task_title    = $task_data[0]->task_title;
			$task_status   = $eod_data->status;
			$hours         = $eod_data->hours;

			$response = array(
				'id'            => $eod_data->id,
				'project_title' => $project_title,
				'task_title'    => $task_title,
				'task_status'   => $task_status,
				'hours'         => $hours,
			);

			wp_send_json_success( $response );
		} else {
			wp_send_json_error( 'EOD data not found.' );
		}
	}

	/**
	 * Updates EOD (End of Day) report data for a user.
	 *
	 * This function processes POST data to update the EOD report entry
	 * in the database. It is usually triggered via an AJAX call from the frontend.
	 *
	 * @return void Outputs JSON response or performs a redirect.
	 */
	public function voidempo_update_eod_data() {

		check_ajax_referer( 'manager_ajax_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}
		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}


		global $wpdb;

		if ( ! isset( $_POST['eod_id'] ) || ! isset( $_POST['task_status'] ) || ! isset( $_POST['hours'] ) ) {
			wp_send_json_error( 'Required fields are missing.' );
		}

		$eod_id      = intval( $_POST['eod_id'] );
		$task_status = sanitize_text_field( wp_unslash( $_POST['task_status'] ) );
		$hours       = sanitize_text_field( wp_unslash( $_POST['hours'] ) );

		$updated = $wpdb->update(
			$wpdb->prefix . 'voidempo_eod',
			array(
				'status'       => $task_status,
				'hours'        => $hours,
				'updated_date' => current_time( 'mysql' ),
			),
			array( 'id' => $eod_id )
		);
		if ( $updated !== false ) {
			wp_cache_delete( 'eod_' . $eod_id, 'voidempo_eod' );
		}
		if ( $updated !== false ) {
			wp_send_json_success( 'EOD updated successfully' );
		} else {
			wp_send_json_error( 'Error updating EOD' );
		}
	}

	/**
	 * AJAX callback to update task details.
	 *
	 * Handles updates to task information such as title, description,
	 * start date, end date, status, etc., via POST data.
	 *
	 * @return void Outputs a JSON response with update status.
	 */
	public function voidempo_update_task_details_callback() {

		check_ajax_referer( 'manager_ajax_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}
		if ( ! ( current_user_can( 'manage_options' ) || current_user_can( 'voidempo_manager_access' ) ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}


		global $wpdb;

		$title       = '';
		$description = '';
		$status      = '';
		$manager_id  = 0;

		if ( empty( $_POST['task_id'] ) ) {
			wp_send_json_error( 'Invalid Task ID' );
			wp_die();
		}
			$task_id = intval( wp_unslash( $_POST['task_id'] ) );
		if ( $task_id <= 0 ) {
			wp_send_json_error( 'Invalid Task ID' );
			wp_die();
		}

		if ( isset( $_POST['title'] ) ) {
			$title = sanitize_text_field( wp_unslash( $_POST['title'] ) );
		}

		if ( isset( $_POST['description'] ) ) {
			$description = sanitize_textarea_field( wp_unslash( $_POST['description'] ) );
		}

		if ( isset( $_POST['status'] ) ) {
			$status = sanitize_text_field( wp_unslash( $_POST['status'] ) );
		}

		if ( isset( $_POST['manager_id'] ) ) {
			$manager_id = intval( $_POST['manager_id'] );
		}
		$member_ids_raw = '';
		$estimated_time = '';

		if ( isset( $_POST['member_ids'] ) ) {
			$member_ids_raw = sanitize_text_field( wp_unslash( $_POST['member_ids'] ) );
		}

		if ( isset( $_POST['estimated_time'] ) ) {
			$estimated_time = sanitize_text_field( wp_unslash( $_POST['estimated_time'] ) );
		}

		$updated = $wpdb->update(
			"{$wpdb->prefix}voidempo_task",
			array(
				'task_title'       => $title,
				'task_description' => $description,
				'status'           => $status,
				'manager_id'       => $manager_id,
				'user_id'          => $member_ids_raw,
				'estimated_hours'  => $estimated_time,
			),
			array( 'id' => $task_id ),
			array( '%s', '%s', '%s', '%d', '%s', '%s' ),
			array( '%d' )
		);

		if ( $updated !== false ) {
			wp_cache_delete( 'task_data_' . $task_id, 'voidempo_task' );
		}

		$cache_key   = 'task_data_' . $task_id;
		$cache_group = 'voidempo_task';
		$task_data   = wp_cache_get( $cache_key, $cache_group );

		if ( false === $task_data ) {
			$task_data = $wpdb->get_row(
				$wpdb->prepare(
					"SELECT project_id FROM {$wpdb->prefix}voidempo_task WHERE id = %d",
					$task_id
				)
			);
			wp_cache_set( $cache_key, $task_data, $cache_group, 300 );
		}

		if ( $task_data ) {
			$project_id = intval( $task_data->project_id );

			if ( ! empty( $member_ids_raw ) ) {
				update_post_meta( $project_id, 'voidempo_project_members', $member_ids_raw );
			}
				update_post_meta( $project_id, 'voidempo_project_manager', $manager_id );
		}

		if ( $updated !== false ) {
			wp_send_json_success( 'Task and related metadata updated' );
		} else {
			wp_send_json_error( 'Update failed or no changes made' );
		}
	}

	/**
	 * Handles AJAX request to delete a user task.
	 *
	 * This function verifies the nonce, receives the task ID,
	 * and deletes the specified task from the database.
	 *
	 * @return void Sends a JSON response back to the client.
	 */
	public function voidempo_usertask_delete() {

		check_ajax_referer( 'manager_ajax_nonce', 'security' );

		if ( ! is_user_logged_in() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
			wp_die();
		}

		if (! current_user_can( 'manage_options' ) && ! current_user_can( 'voidempo_manager_access' ) ) {
			wp_send_json_error( array( 'message' => 'Unauthorized access!' ), 403 );
		}

		global $wpdb;
		$task_id = '';

		if ( isset( $_POST['task_id'] ) ) {
			$task_id = sanitize_text_field( wp_unslash( $_POST['task_id'] ) );
		}

		$delete_reason      = isset( $_POST['delete_reason'] ) ? sanitize_text_field( wp_unslash( $_POST['delete_reason'] ) ) : '';
		$update_assign_task = $wpdb->update(
			$wpdb->prefix . 'voidempo_task',
			array(
				'status'    => 'Cancelled',
				'is_delete' => 1,
			),
			array( 'id' => $task_id )
		);
		if ( false === $update_assign_task ) {
		} else {
			wp_cache_delete( 'task_' . $task_id, 'voidempo_task' );
		}

		$task_data  = voidempo_fetch_tasksby_taskid( $task_id );
		$task_title = $task_data[0]->task_title;

		$description     = "Task {$task_title} is deleted because of reason - {$delete_reason}";
		$current_user_id = get_current_user_id();
		$date_created    = gmdate( 'Y-m-d H:i:s' );

		$inserted = $wpdb->query(
			$wpdb->prepare(
				"INSERT INTO {$wpdb->prefix}voidempo_task_log 
				(user_id, description, object_id, date_created) 
			VALUES (%d, %s, %d, %s)",
				$current_user_id,
				$description,
				$task_id,
				$date_created
			)
		);

		if ( false === $inserted ) {
		} else {
			wp_cache_delete( 'task_logs_' . $task_id, 'task_logs' );
		}

		$json_array = array();
		if ( $update_assign_task == '1' ) {
			$json_array['msg']     = 'deleted';
			$json_array['task_id'] = $task_id;
			echo wp_json_encode( $json_array );
		}
		wp_die();
	}
}
