<?php //phpcs:ignore

/**
 * File: Zmeet_Ajax.php
 *
 * The Zmeet_Ajax class handles AJAX requests and provides functionalities for generating referral coupons.
 *
 * @package ECRE
 * @since   1.0.0
 */

namespace SOVLIX\ZMEET;

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

if ( ! class_exists( 'Zmeet_Ajax' ) ) {
	/**
	 * The Zmeet_Ajax class handles AJAX requests and provides functionalities for generating referral coupons.
	 *
	 * @since 1.0.0
	 */
	class Zmeet_Ajax {
		/**
		 * Zmeet_Ajax constructor.
		 *
		 * Initializes the class and sets up AJAX request handlers.
		 */
		public function __construct() {
			add_action( 'wp_ajax_zmeet_zoom_meeting_sign', array( $this, 'zmeet_generate_signature' ) );
			add_action( 'wp_ajax_nopriv_zmeet_zoom_meeting_sign', array( $this, 'zmeet_generate_signature' ) );
			add_action( 'wp_ajax_zmeet_meeting_action', array( $this, 'handle_zmeet_meeting_action' ) );
			add_action( 'wp_ajax_nopriv_zmeet_meeting_action', array( $this, 'handle_zmeet_meeting_action' ) );
			add_action( 'wp_ajax_zmeet_meeting_list', array( $this, 'zmeet_meeting_lists' ) );
			add_action( 'wp_ajax_nopriv_zmeet_meeting_list', array( $this, 'zmeet_meeting_lists' ) );
			add_action( 'wp_ajax_zmeet_renew_zoom_oauth', array( $this, 'zmeet_renew_zoom_oauth_callback' ) );
			add_action( 'wp_ajax_zmeet_save_visibility_mode', array( $this, 'zmeet_save_visibility_mode' ) );
			add_action( 'wp_ajax_zmeet_fetch_roles', array( $this, 'zmeet_fetch_roles' ) );
			add_action( 'wp_ajax_zmeet_fetch_users', array( $this, 'zmeet_fetch_users' ) );
			add_action( 'wp_ajax_zmeet_fetch_users_by_ids', array( $this, 'zmeet_fetch_users_by_ids' ) );
			add_action( 'wp_ajax_zmeet_dismiss_notice', array( $this, 'zmeet_dismiss_notice' ) );
		}

		/**
		 * Handles AJAX requests for fetching meeting lists.
		 *
		 * This function verifies the nonce for security, fetches the list of meetings,
		 * and returns the meetings as a JSON response. It is intended to be used as a
		 * callback for AJAX requests in WordPress.
		 *
		 * @since 1.0.0
		 *
		 * @return void
		 */
		public function zmeet_meeting_lists() {
			// Verify nonce for security.
			$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
			if ( ! wp_verify_nonce( $nonce, 'zmeet_frontend_nonce' ) ) {
				wp_send_json_error( __( 'Invalid security token.', 'zoomeet' ), 403 );
				return;
			}

			$page_id           = isset( $_POST['page_id'] ) ? absint( $_POST['page_id'] ) : 0;
			$visibility_mode   = isset( $_POST['visibility_mode'] ) ? sanitize_text_field( wp_unslash( $_POST['visibility_mode'] ) ) : 'user';
			$roles             = isset( $_POST['roles'] ) ? json_decode( wp_unslash( $_POST['roles'] ), true ) : array();
			$users             = isset( $_POST['users'] ) ? json_decode( wp_unslash( $_POST['users'] ), true ) : array();
			$use_passed_values = isset( $_POST['use_passed_values'] ) && '1' === $_POST['use_passed_values'] ? true : false;

			// If it's not an admin and not using passed values, get the saved visibility settings for the page.
			if ( ! current_user_can( 'manage_options' ) && ! $use_passed_values ) {
				$visibility_mode = get_post_meta( $page_id, '_zmeet_visibility_mode', true );
				$visibility_mode = $visibility_mode ? $visibility_mode : 'user';
				$roles           = get_post_meta( $page_id, '_zmeet_visibility_roles', true );
				$users           = get_post_meta( $page_id, '_zmeet_visibility_users', true );
			}

			$meetings = zmeet_meetings_by_mode( $visibility_mode, $page_id, $roles, $users, $use_passed_values );

			wp_send_json_success( $meetings );
		}

		/**
		 * Save visibility mode for a page.
		 */
		public function zmeet_save_visibility_mode() {
			check_ajax_referer( 'zmeet_frontend_nonce', 'nonce' );

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( __( 'Unauthorized.', 'zoomeet' ), 403 );
			}

			$page_id = isset( $_POST['page_id'] ) ? absint( $_POST['page_id'] ) : 0;
			$mode    = isset( $_POST['mode'] ) ? sanitize_text_field( wp_unslash( $_POST['mode'] ) ) : 'user';
			$roles   = isset( $_POST['roles'] ) ? json_decode( wp_unslash( $_POST['roles'] ), true ) : array();
			$users   = isset( $_POST['users'] ) ? json_decode( wp_unslash( $_POST['users'] ), true ) : array();

			update_post_meta( $page_id, '_zmeet_visibility_mode', $mode );
			update_post_meta( $page_id, '_zmeet_visibility_roles', $roles );
			update_post_meta( $page_id, '_zmeet_visibility_users', $users );

			wp_send_json_success( __( 'Visibility settings saved.', 'zoomeet' ) );
		}

		/**
		 * Fetch users for visibility settings.
		 */
		public function zmeet_fetch_users() {
			check_ajax_referer( 'zmeet_frontend_nonce', 'nonce' );

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( __( 'Unauthorized.', 'zoomeet' ), 403 );
			}

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

			$users = get_users(
				array(
					'search'         => '*' . $search . '*',
					'search_columns' => array( 'user_login', 'user_email', 'display_name' ),
					'number'         => 20,
				)
			);

			$data = array();
			foreach ( $users as $user ) {
				$data[] = array(
					'value' => $user->ID,
					'label' => $user->display_name . ' (' . $user->user_email . ')',
				);
			}

			wp_send_json_success( $data );
		}

		/**
		 * Fetch user roles for visibility settings.
		 */
		public function zmeet_fetch_roles() {
			check_ajax_referer( 'zmeet_frontend_nonce', 'nonce' );

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( __( 'Unauthorized.', 'zoomeet' ), 403 );
			}

			global $wp_roles;
			$roles = $wp_roles->get_names();

			$data = array();
			foreach ( $roles as $role_key => $role_name ) {
				$data[] = array(
					'value' => $role_key,
					'label' => $role_name,
				);
			}

			wp_send_json_success( $data );
		}

		/**
		 * Dismiss admin notice for a certain period.
		 */
		public function zmeet_dismiss_notice() {
			check_ajax_referer( 'zmeet_admin_nonce', 'nonce' );

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( __( 'Unauthorized.', 'zoomeet' ), 403 );
			}

			$id       = isset( $_POST['notice_id'] ) ? sanitize_text_field( wp_unslash( $_POST['notice_id'] ) ) : '';
			$duration = isset( $_POST['duration'] ) ? sanitize_text_field( wp_unslash( $_POST['duration'] ) ) : '7';

			if ( empty( $id ) ) {
				wp_send_json_error( __( 'Notice ID is missing.', 'zoomeet' ) );
			}

			$dismissed_notices = get_option( 'zmeet_dismissed_notices', array() );

			if ( 'forever' === $duration ) {
				$dismissed_notices[ $id ] = -1;
			} else {
				$days                     = absint( $duration );
				$dismissed_notices[ $id ] = time() + ( $days * DAY_IN_SECONDS );
			}

			update_option( 'zmeet_dismissed_notices', $dismissed_notices );

			wp_send_json_success();
		}


		/**
		 * Fetch users by IDs.
		 */
		public function zmeet_fetch_users_by_ids() {
			check_ajax_referer( 'zmeet_frontend_nonce', 'nonce' );

			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( __( 'Unauthorized.', 'zoomeet' ), 403 );
			}

			$user_ids = isset( $_POST['user_ids'] ) ? array_map( 'absint', (array) $_POST['user_ids'] ) : array();

			if ( empty( $user_ids ) ) {
				wp_send_json_success( array() );
			}

			$users = get_users( array( 'include' => $user_ids ) );

			$data = array();
			foreach ( $users as $user ) {
				$data[] = array(
					'value' => $user->ID,
					'label' => $user->display_name . ' (' . $user->user_email . ')',
				);
			}

			wp_send_json_success( $data );
		}


		/**
		 * Generate Zoom meeting signature for SDK authentication.
		 *
		 * Handles AJAX request to generate a signature required for Zoom SDK authentication.
		 * Expects JSON payload with meetingNumber and role parameters.
		 *
		 * @since 1.0.0
		 * @return void Outputs JSON response and terminates execution.
		 */
		public function zmeet_generate_signature() {
			// Verify nonce for security.
			if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ?? '' ) ), 'zmeet_signature_nonce' ) ) {
				wp_send_json_error( 'Invalid nonce' );
				return;
			}

			// Get and validate input.
			$request_body = file_get_contents( 'php://input' );
			if ( empty( $request_body ) ) {
				wp_send_json_error( 'Invalid request body' );
				return;
			}

			$request = json_decode( $request_body, true );
			if ( json_last_error() !== JSON_ERROR_NONE ) {
				wp_send_json_error( 'Invalid JSON format' );
				return;
			}

			// Validate required parameters.
			$meeting_number = sanitize_text_field( $request['meetingNumber'] ?? '' );
			$role           = absint( $request['role'] ?? 0 );

			if ( empty( $meeting_number ) || empty( $role ) ) {
				wp_send_json_error( 'Missing required parameters' );
				return;
			}

			// Get Zoom settings with proper default.
			$zoom_settings = get_option( 'zmeet_zoom_settings', array() );

			// Validate API credentials exist.
			$api_key    = sanitize_text_field( $zoom_settings['sdk_client_id'] ?? '' );
			$api_secret = sanitize_text_field( $zoom_settings['sdk_client_secret'] ?? '' );

			if ( empty( $api_key ) || empty( $api_secret ) ) {
				wp_send_json_error( 'Missing API credentials' );
				return;
			}

			// Generate signature.
			$timestamp = ( time() * 1000 ) - 30000;
			$data      = base64_encode( $api_key . $meeting_number . $timestamp . $role );
			$hash      = hash_hmac( 'sha256', $data, $api_secret, true );
			$signature = $api_key . '.' . $meeting_number . '.' . $timestamp . '.' . $role . '.' . base64_encode( $hash );

			// Encode signature.
			$encoded_signature = rtrim( strtr( base64_encode( $signature ), '+/', '-_' ), '=' );

			// Send JSON response.
			wp_send_json_success( array( 'signature' => $encoded_signature ) );
		}

		/**
		 * Handle end meeting action
		 */
		public function handle_zmeet_meeting_action() {
			// Verify nonce for security.
			$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
			if ( ! wp_verify_nonce( $nonce, 'zmeet_frontend_nonce' ) ) {
				wp_send_json_error( 'Invalid nonce.' );
			}

			$response = '';

			// Retrieve and sanitize posted data.
			$meeting_id     = isset( $_POST['meeting_id'] ) ? sanitize_text_field( wp_unslash( $_POST['meeting_id'] ) ) : '';
			$post_id        = isset( $_POST['post_id'] ) ? sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) : '';
			$meeting_status = isset( $_POST['meeting_status'] ) ? sanitize_text_field( wp_unslash( $_POST['meeting_status'] ) ) : '';

			if ( 'end' === $meeting_status ) {
				update_post_meta( $post_id, 'zmeet_meeting_status', 'end' );
				$response = 'Meeting ended successfully.';
			}

			if ( 'resume' === $meeting_status ) {
				update_post_meta( $post_id, 'zmeet_meeting_status', 'resume' );
				$response = 'Meeting resumed successfully.';
			}

			if ( 'start' === $meeting_status ) {
				update_post_meta( $post_id, 'zmeet_meeting_start_status', 'start' );
				$response = 'Meeting started successfully.';
			}

			if ( 'stop' === $meeting_status ) {
				update_post_meta( $post_id, 'zmeet_meeting_start_status', 'stop' );
				$response = 'Meeting stoped successfully.';
			}

			// Example: Respond with a success message.
			wp_send_json_success( $response );
		}

		/**
		 * Handles the renewal of Zoom OAuth tokens via AJAX.
		 *
		 * This function verifies the request, checks user permissions, retrieves
		 * the stored Zoom OAuth credentials, and attempts to renew the access token.
		 * If successful, it saves the new token; otherwise, it returns an error response.
		 *
		 * @since 1.0.0
		 * @return void Outputs a JSON response indicating success or failure.
		 */
		public function zmeet_renew_zoom_oauth_callback() {
			// Verify nonce.
			$nonce = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
			if ( ! wp_verify_nonce( $nonce, 'zmeet_admin_nonce' ) ) {
				wp_send_json_error( array( 'message' => 'Invalid nonce.' ) );
			}

			// Check user capability.
			if ( ! current_user_can( 'manage_options' ) ) {
				wp_send_json_error( array( 'message' => 'Unauthorized request.' ) );
			}

			// Get Zoom settings from options.
			$zoom_settings = get_option( 'zmeet_zoom_settings' );

			// Validate settings.
			if ( ! is_array( $zoom_settings ) || empty( $zoom_settings ) ) {
				update_option( 'zmeet_zoom_global_oauth_data', '' );
				wp_send_json_error( array( 'message' => 'Renew failed. Set OAuth credentials first.' ) );
			}

			// Extract credentials.
			$account_id    = $zoom_settings['oauth_account_id'] ?? '';
			$client_id     = $zoom_settings['oauth_client_id'] ?? '';
			$client_secret = $zoom_settings['oauth_client_secret'] ?? '';

			// Ensure all required fields are set.
			if ( empty( $account_id ) || empty( $client_id ) || empty( $client_secret ) ) {
				update_option( 'zmeet_zoom_global_oauth_data', '' );
				wp_send_json_error( array( 'message' => 'Renew failed. Missing OAuth credentials.' ) );
			}

			// Attempt to renew the access token.
			$zoom_auth = \SOVLIX\ZMEET\Zoom\Zmeet_S2SO_Auth::get_instance();
			$result    = $zoom_auth->generate_and_save_access_token( $account_id, $client_id, $client_secret );

			if ( is_wp_error( $result ) ) {
				update_option( 'zmeet_zoom_global_oauth_data', '' );
				wp_send_json_error( array( 'message' => 'OAuth renewal failed: ' . $result->get_error_message() ) );
			}

			// Respond with success.
			wp_send_json_success( array( 'message' => 'OAuth Token Renewed Successfully' ) );
		}
	}
}
