<?php //phpcs:ignore
/**
 * Routes for meetings
 *
 * @package SOVLIX\WEMEET
 */

namespace SOVLIX\WEMEET\API;

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

//phpcs:ignore
use WP_REST_Controller;
//phpcs:ignore
use WP_REST_Server;
//phpcs:ignore
use WP_Error;

if ( ! class_exists( 'Wemeet_Meetings' ) ) {
	/**
	 * Wemeet_Meetings Class
	 */
	class Wemeet_Meetings extends \WP_REST_Controller {

		/**
		 * Webex Api class.
		 *
		 * @var Wemeet_Webex_Api
		 */
		private $webex_api;

		/**
		 * Wemeet_Meetings constructor
		 */
		public function __construct() {
			$this->namespace = 'wemeet/v1';
			$this->rest_base = 'meetings';
			$this->webex_api = \SOVLIX\WEMEET\API\Webex_Api::get_instance();
		}

		/**
		 * Register REST API routes
		 *
		 * @since 1.0.0
		 */
		public function register_routes() {

			register_rest_route(
				$this->namespace,
				'/' . $this->rest_base,
				array(
					array(
						'methods'             => WP_REST_Server::READABLE,
						'callback'            => array( $this, 'get_items' ),
						'permission_callback' => array( $this, 'check_permissions' ),
					),
					array(
						'methods'             => WP_REST_Server::CREATABLE,
						'callback'            => array( $this, 'create_item' ),
						'permission_callback' => array( $this, 'check_permissions' ),
					),

				)
			);

			register_rest_route(
				$this->namespace,
				'/' . $this->rest_base . '/(?P<id>[\d]+)',
				array(
					'args' => array(
						'id' => array(
							'description' => __( 'Unique identifier for the object.', 'wemeet' ),
							'type'        => 'integer',
						),
					),
				//phpcs:ignore
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_item' ),
					'permission_callback' => array( $this, 'check_permissions' ),
					'args'                => array(
						'context' => $this->get_context_param( array( 'default' => 'view' ) ),
					),
				),
				//phpcs:ignore
				array(
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'update_item' ),
					'permission_callback' => array( $this, 'check_permissions' ),
				),
				//phpcs:ignore
				array(
					'methods'             => WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'delete_item' ),
					'permission_callback' => array( $this, 'check_permissions' ),
				),
				)
			);

			register_rest_route(
				$this->namespace,
				'/' . $this->rest_base . '/delete-multiple',
				array(
					'methods'             => WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'delete_multiple_items' ),
					'permission_callback' => array( $this, 'check_permissions' ),
				)
			);
		}

		/**
		 * Check if the current user has permission to edit posts.
		 *
		 * This function checks if the current user has the capability to edit posts.
		 * It returns true if the user has the 'edit_posts' capability, and false otherwise.
		 *
		 * @return bool True if the current user can edit posts, false otherwise.
		 */
		public function check_permissions() {
			return is_user_logged_in();
			//return current_user_can( 'edit_posts' );
		}

		/**
		 * Retrieves all meetings.
		 *
		 * @param mixed $request Post request.
		 *
		 * @return mixed
		 */
		public function get_items( $request ) {

			$data     = array();
			$meetings = wemeet_meetings();

			foreach ( $meetings as $meeting ) {
				$response = $this->prepare_item_for_response( $meeting, $request );
				$data[]   = $this->prepare_response_for_collection( $response );
			}

			$response = rest_ensure_response( $data );
			return $response;
		}

		/**
		 * Get the address, if the ID is valid.
		 *
		 * @param int $id Supplied ID.
		 *
		 * @return Object|\WP_Error
		 */
		protected function get_meeting( $id ) {
			$meeting = wemeet_meeting( $id );

			if ( ! $meeting ) {
				return new WP_Error(
					'rest_contact_invalid_id',
					__( 'Invalid contact ID.', 'wemeet' ),
					array( 'status' => 404 )
				);
			}

			return $meeting;
		}

		/**
		 * Retrieves one item from the collection.
		 *
		 * @param \WP_REST_Request $request Post request.
		 *
		 * @return \WP_Error|\WP_REST_Response
		 */
		public function get_item( $request ) {
			$meeting  = wemeet_meeting( $request['id'] );
			$response = $this->prepare_item_for_response( $meeting, $request );
			$response = rest_ensure_response( $response );

			return $response;
		}

		/**
		 * Creates one item from the collection.
		 *
		 * @param \WP_REST_Request $request Post request.
		 *
		 * @return \WP_Error|WP_REST_Response
		 */
		public function create_item( $request ) {
			$meeting = $this->prepare_item_for_database( $request );

			if ( is_wp_error( $meeting ) ) {
				return $meeting;
			}

			$meeting_settings = maybe_unserialize( $meeting['settings'] );

			$duration = ! empty( $meeting_settings['duration_hours'] ) || ! empty( $meeting_settings['duration_minutes'] ) ? wemeet_convert_to_minutes( $meeting_settings['duration_hours'], $meeting_settings['duration_minutes'] ) : 40;

			$webex_meeting_data = wemeet_prepare_webex_meeting_data( $meeting['title'], $meeting_settings, $duration );

			$webex_response = $this->webex_api->create_meeting( $webex_meeting_data );

			if ( ! empty( $webex_response ) && ! isset( $webex_response['errors'] ) ) {
				$meeting_id = wemeet_insert_meeting( $meeting['title'], $meeting['settings'], $meeting['meeting_description'] );
				update_post_meta( $meeting_id, 'wemeet_webex_meeting_id', $webex_response['id'] );
				update_post_meta( $meeting_id, 'wemeet_webex_join_link', $webex_response['webLink'] );
				update_post_meta( $meeting_id, 'wemeet_webex_meeting_duration', $duration );
				update_post_meta( $meeting_id, 'wemeet_webex_details', $webex_response );
			}

			return rest_ensure_response( $webex_response );
		}

		/**
		 * Updates one item from the collection.
		 *
		 * @param \WP_REST_Request $request Post request.
		 *
		 * @return \WP_Error|\WP_REST_Response
		 */
		public function update_item( $request ) {
			$meeting = $this->prepare_item_for_database( $request );

			$meeting_settings = maybe_unserialize( $meeting['settings'] );

			// Webex meeting update.
			$duration = ! empty( $meeting_settings['duration_hours'] ) || ! empty( $meeting_settings['duration_minutes'] ) ? wemeet_convert_to_minutes( $meeting_settings['duration_hours'], $meeting_settings['duration_minutes'] ) : 40;

			$webex_meeting_id = get_post_meta( $meeting['id'], 'wemeet_webex_meeting_id', true );

			$webex_meeting_data = wemeet_prepare_webex_meeting_data( $meeting['title'], $meeting_settings, $duration );
			$webex_response     = $this->webex_api->update_meeting( $webex_meeting_id, $webex_meeting_data );

			if ( ! empty( $webex_response ) && ! isset( $webex_response['errors'] ) ) {
				$meeting_id = wemeet_update_meeting( $meeting['title'], $meeting['settings'], $meeting['id'], $meeting['meeting_description'] );
				update_post_meta( $meeting['id'], 'wemeet_webex_join_link', $webex_response['webLink'] );
				update_post_meta( $meeting['id'], 'wemeet_webex_meeting_duration', $duration );
				update_post_meta( $meeting['id'], 'wemeet_webex_details', $webex_response );
			}

			return rest_ensure_response( $webex_response );
		}

		/**
		 * Prepares one item for create or update operation.
		 *
		 * @param \WP_REST_Request $request Post request.
		 *
		 * @return \WP_Error|object
		 */
		protected function prepare_item_for_database( $request ) {
			$posted = json_decode( $request->get_body() );

			$prepared = array();
			$settings = array();

			if ( isset( $posted ) ) {
				foreach ( $posted as $key => $post ) {
					$settings[ $key ] = $post;
				}

				unset( $settings['title'] );
				unset( $settings['meeting_description'] );

				$settings['host'] = get_current_user_id();

				if ( isset( $posted->id ) ) {
					$prepared['id'] = $posted->id;
				}

				$prepared['title']               = sanitize_text_field( $posted->title );
				$prepared['settings']            = maybe_serialize( $settings );
				$prepared['meeting_description'] = $posted->meeting_description;
			}

			return $prepared;
		}

		/**
		 * Prepares the item for the REST response.
		 *
		 * @param mixed            $item    WordPress representation of the item.
		 * @param \WP_REST_Request $request Request object.
		 *
		 * @return \WP_Error|WP_REST_Response
		 */
		public function prepare_item_for_response( $item, $request ) {
			$data   = array();
			$fields = $this->get_fields_for_response( $request );

			if ( isset( $item['id'] ) && in_array( 'id', $fields, true ) ) {
				$data['id'] = (int) $item['id'];
			}

			if ( isset( $item['title'] ) && in_array( 'title', $fields, true ) ) {
				$data['title'] = $item['title'];
			}

			if ( isset( $item['settings'] ) && in_array( 'settings', $fields, true ) ) {
				$data['settings'] = $item['settings'];
			}

			if ( isset( $item['meeting_description'] ) && in_array( 'meeting_description', $fields, true ) ) {
				$data['meeting_description'] = $item['meeting_description'];
			}

			if ( isset( $item['date'] ) && in_array( 'date', $fields, true ) ) {
				$data['date'] = mysql_to_rfc3339( $item['date'] );
			}

			$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
			$data    = $this->filter_response_by_context( $data, $context );

			$response = rest_ensure_response( $data );
			$response->add_links( $this->prepare_links( $item ) );

			return $response;
		}


		/**
		 * Deletes one item from the collection.
		 *
		 * @param \WP_REST_Request $request Request object.
		 *
		 * @return \WP_Error|WP_REST_Response
		 */
		public function delete_item( $request ) {
			$serialized_settings = get_post_meta( $request['id'], 'wemeet__meeting_settings', true );
			$settings            = maybe_unserialize( $serialized_settings );

			if ( 'webex' === $settings['selected_platform'] ) {
				$webex_meeting_id      = get_post_meta( $request['id'], 'wemeet_webex_meeting_id', true );
				$webex_meeting_deleted = $this->webex_api->delete_meeting( $webex_meeting_id );
			}

			$deleted = wemeet_delete_meeting( $request['id'] );

			if ( ! $deleted ) {
				return new WP_Error(
					'rest_not_deleted',
					__( 'Sorry, the address could not be deleted.', 'wemeet' ),
					array( 'status' => 400 )
				);
			}

			$data = array(
				'deleted' => true,
			);

			$response = rest_ensure_response( $data );

			return $data;
		}

		/**
		 * Deletes multiple items from the collection.
		 *
		 * @param \WP_REST_Request $request Request object.
		 *
		 * @return \WP_Error|WP_REST_Response
		 */
		public function delete_multiple_items( $request ) {
			$ids = $request->get_param( 'ids' );

			if ( empty( $ids ) || ! is_array( $ids ) ) {
				return new \WP_Error(
					'rest_invalid_param',
					__( 'Invalid or missing parameter: ids.', 'wemeet' ),
					array( 'status' => 400 )
				);
			}

			$response_data = array();

			foreach ( $ids as $id ) {

				$serialized_settings   = get_post_meta( $id, 'wemeet__meeting_settings', true );
				$settings              = maybe_unserialize( $serialized_settings );
				$webex_meeting_id      = get_post_meta( $id, 'wemeet_webex_meeting_id', true );
				$webex_meeting_deleted = $this->webex_api->delete_meeting( $webex_meeting_id );

				$deleted = wemeet_delete_meeting( $id );

				if ( is_wp_error( $deleted ) ) {
					// Handle error if needed.
					$response_data[] = array(
						'id'     => $id,
						'status' => 'error',
					);
				} else {
					$response_data[] = array(
						'id'     => $id,
						'status' => 'deleted',
					);
				}
			}

			return rest_ensure_response( $response_data );
		}


		/**
		 * Prepares links for the request.
		 *
		 * @param mixed $item Get Post.
		 *
		 * @return array Links for the given post.
		 */
		protected function prepare_links( $item ) {
			$base = sprintf( '%s/%s', $this->namespace, $this->rest_base );

			$links = array();

			if ( isset( $item['id'] ) ) {
				$links['self'] = array(
					'href' => rest_url( trailingslashit( $base ) . $item['id'] ),
				);
			}

			$links['collection'] = array(
				'href' => rest_url( $base ),
			);

			return $links;
		}


		/**
		 * Retrieves the contact schema, conforming to JSON Schema.
		 *
		 * @return array
		 */
		public function get_item_schema() {
			if ( $this->schema ) {
				return $this->add_additional_fields_schema( $this->schema );
			}

			$schema = array(
				'$schema'    => 'http://json-schema.org/draft-04/schema#',
				'title'      => 'contact',
				'type'       => 'object',
				'properties' => array(
					'id'                  => array(
						'description' => __( 'Unique identifier for the object.', 'wemeet' ),
						'type'        => 'integer',
						'context'     => array( 'view', 'edit' ),
						'readonly'    => true,
					),
					'title'               => array(
						'description' => __( 'Name of the meeting.', 'wemeet' ),
						'type'        => 'string',
						'context'     => array( 'view', 'edit' ),
						'required'    => true,
						'arg_options' => array(
							'sanitize_callback' => 'sanitize_text_field',
						),
					),
					'settings'            => array(
						'description' => __( 'Meeting setting', 'wemeet' ),
						'type'        => 'string',
						'context'     => array( 'view', 'edit' ),
						'required'    => true,
					),
					'meeting_description' => array(
						'description' => __( 'Meeting setting', 'wemeet' ),
						'type'        => 'string',
						'context'     => array( 'view', 'edit' ),
						'required'    => true,
					),
					'date'                => array(
						'description' => __( "The date the object was published, in the site's timezone.", 'wemeet' ),
						'type'        => 'string',
						'format'      => 'date-time',
						'context'     => array( 'view' ),
						'readonly'    => true,
					),
				),
			);

			$this->schema = $schema;

			return $this->add_additional_fields_schema( $this->schema );
		}
	}
}
