<?php

namespace Bookify\Controllers\REST;

use WP_REST_Response;
use WP_Error;
use Bookify\Models\Bookify_Appointment_Models;
use Bookify\Models\Bookify_Service_Models;
use Bookify\Controllers\Bookify_Helper;
use BookifyPro\Models\Bookify_Pro_Location_Models;
use BookifyPro\Controllers\Bookify_Pro_Helper;

// don't call the file directly
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'Bookify_Appointments_Rest_API' ) ) {

	class Bookify_Appointments_Rest_API {

		public function __construct() {

			add_action( 'rest_api_init' , array( $this, 'rest_api_appointments' ) );
		}

		public function rest_api_appointments() {

			register_rest_route('bookify/v1', '/appointments', array(
				'methods'               => 'GET',
				'callback'              => array( $this, 'rest_appointments_data_callback' ),
				'permission_callback'   => array( $this, 'verify_nonce_and_permissions' )
			)); 

			register_rest_route('bookify/v1', '/add-appointment', array(
				'methods'               => 'POST',
				'callback'              => array( $this, 'rest_add_appointments_data_callback' ),
				'permission_callback'   => array( $this, 'verify_nonce_and_permissions' )
			)); 

			register_rest_route('bookify/v1', '/delete-appointment', array(
				'methods'               => 'POST',
				'callback'              => array( $this, 'rest_delete_appointments_data_callback' ),
				'permission_callback'   => array( $this, 'verify_nonce_and_permissions' )
			));

			register_rest_route('bookify/v1', '/update-appointment', array(
				'methods'               => 'POST',
				'callback'              => array( $this, 'rest_update_appointments_data_callback' ),
				'permission_callback'   => array( $this, 'verify_nonce_and_permissions' )
			));

			register_rest_route('bookify/v1', '/available-slots', array(
				'methods'               => 'POST',
				'callback'              => array( $this, 'rest_available_slots_callback' ),
				'permission_callback'   => array( $this, 'verify_nonce_and_permissions' )
			)); 
		}

		public function verify_nonce_and_permissions( $request ) {
			$nonce = $request->get_header('X-WP-Nonce'); 

			if ( !$nonce ) {
				return new WP_Error( 
					'rest_missing_nonce', 
					__('You do not have permission to access this resource. Please contact the administrator if you believe this is an error.', 'bookify'), 
					array( 
						'status' => 403, 
						'message' => 'Nonce is missing.' 
					) 
				);
			}

			return true;
		}

		public function rest_update_appointments_data_callback( $request ) {

			$nonce = $request->get_header('X-WP-Nonce');
			if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
				return new WP_Error( 'rest_forbidden', __('Invalid nonce.', 'bookify'), array( 'status' => 403 ) );
			}
			
			$general_settings = get_option( 'bookify_general_settings');
			$default_appointment_status = is_array( $general_settings ) && isset( $general_settings['DefaultAppointmentStatus'] ) ? $general_settings['DefaultAppointmentStatus'] : 'Pending';

			$params = $request->get_json_params();
			
			$appointment_id = isset( $params['appointment_id'] ) && ! empty( $params['appointment_id'] ) ? sanitize_text_field( $params['appointment_id'] ) : '';
			$appointment_location = isset( $params['appointment_location'] ) && ! empty( $params['appointment_location'] ) ? sanitize_text_field( $params['appointment_location'] ) : 0;
			$appointment_service = isset( $params['appointment_service'] ) && ! empty( $params['appointment_service'] ) ? sanitize_text_field( $params['appointment_service'] ) : '';
			$appointment_staff = isset( $params['appointment_staff'] ) && ! empty( $params['appointment_staff'] ) ? sanitize_text_field( $params['appointment_staff'] ) : '';
			$appointment_date = isset( $params['appointment_date'] ) && ! empty( $params['appointment_date'] ) ? sanitize_text_field( $params['appointment_date'] ) : '';
			$appointment_duration = isset( $params['appointment_duration'] ) && ! empty( $params['appointment_duration'] ) ? sanitize_text_field( $params['appointment_duration'] ) : '';
			$appointment_price = isset( $params['appointment_price'] ) && ! empty( $params['appointment_price'] ) ? sanitize_text_field( $params['appointment_price'] ) : '';
			$customer_id = isset( $params['customer_id'] ) && ! empty( $params['customer_id'] ) ? sanitize_text_field( $params['customer_id'] ) : '';
			$appointment_status = isset( $params['appointment_status'] ) && ! empty( $params['appointment_status'] ) ? sanitize_text_field( $params['appointment_status'] ) : $default_appointment_status;
			$note = isset( $params['note'] ) && ! empty( $params['note'] ) ? sanitize_text_field( $params['note'] ) : '';

			if ( ! $appointment_id || ! $appointment_service ||  ! $appointment_staff ||  ! $appointment_date || ! $appointment_duration || ! $appointment_price || ! $customer_id ) {
				return new WP_REST_Response(array(
					'success' => false,
					'message' => 'Please Fill the required fields!',
				), 200);
			}

			$appointment_data = Bookify_Appointment_Models::bookify_get_appointment_by_id( $appointment_id );
			$prev_status = $appointment_data['appointment_status'];

			$data = array(
				'appointment_location' => $appointment_location,
				'appointment_service' => $appointment_service,
				'appointment_staff' => $appointment_staff,
				'appointment_date' => $appointment_date,
				'appointment_duration' => json_encode( explode( ',', $appointment_duration ) ),
				'appointment_price' => $appointment_price,
				'appointment_customer' => $customer_id,
				'appointment_status' => $appointment_status,
				'appointment_note' => $note,
			);

			if ( class_exists('\BookifyPro\Bookify_Pro_Main') && defined( 'BOOKIFY_PRO_LICENCE_ACTIVATED' ) == true ) {
				if ( $prev_status != "Cancelled" && $appointment_status == 'Cancelled' ) {
					Bookify_Pro_Helper::delete_apppintment_from_calendars( $appointment_id );
				}
	
				if ( $appointment_status == 'Cancelled' || $appointment_status == 'On Hold' || $appointment_status == 'Delayed' || $appointment_status == 'Completed' ) {
					Bookify_Pro_Helper::delete_appointment_zoom_meeting( $appointment_id );
					bookify_delete_appointments_meta( $appointment_id, 'zoom_meeting_links' );
				} else {
					Bookify_Pro_Helper::appointment_zoom_meeting( $appointment_id, $data, true );
				}
			}

			$result = Bookify_Appointment_Models::bookify_update_appointment( $appointment_id, $data );

			/**
			 * Action - Sends email on changed status of appointment.
			 * 
			 * @since 1.0
			**/
			do_action( 'bookify_appointment_status_changed_email', $appointment_id, $prev_status, $appointment_status );

			if ( $result ) {
				return new WP_REST_Response(array(
					'success' => $result,
					'message' => 'Appointment has been updated successfully!'
				), 200);
			} else {
				return new WP_REST_Response(array(
					'success' => false,
					'message' => 'Error while updating appointment!'
				), 200);
			}
		}

		public function rest_delete_appointments_data_callback( $request ) {

			$nonce = $request->get_header('X-WP-Nonce');
			if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
				return new WP_Error( 'rest_forbidden', __('Invalid nonce.', 'bookify'), array( 'status' => 403 ) );
			}

			$params = $request->get_json_params();

			$appointment_id = isset( $params['appointment_id'] ) && ! empty( $params['appointment_id'] ) ? sanitize_text_field( $params['appointment_id'] ) : '';

			if ( ! $appointment_id ) {
				return new WP_REST_Response(array(
					'success' => false,
					'message' => 'No appointment id is selected for deleting!',
				), 200);
			}

			if ( class_exists('\BookifyPro\Bookify_Pro_Main') && defined( 'BOOKIFY_PRO_LICENCE_ACTIVATED' ) == true ) {
				Bookify_Pro_Helper::delete_apppintment_from_calendars( $appointment_id );

				Bookify_Pro_Helper::delete_appointment_zoom_meeting( $appointment_id );
			}

			$result = Bookify_Appointment_Models::bookify_delete_appointment( $appointment_id );

			if ( $result ) {

				bookify_delete_appointments_meta( $appointment_id );

				return new WP_REST_Response(array(
					'success' => $result,
					'message' => 'Appointmnet has been deleted successfully!'
				), 200);
			} else {
				return new WP_REST_Response(array(
					'success' => false,
					'message' => 'Error while deleting appointmnet!'
				), 200);
			}
		}

		public function rest_available_slots_callback( $request ) {

			$nonce = $request->get_header('X-WP-Nonce');
			if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
				return new WP_Error( 'rest_forbidden', __('Invalid nonce.', 'bookify'), array( 'status' => 403 ) );
			}

			$params = $request->get_json_params();
		
			$date = isset( $params['date'] ) && ! empty( $params['date'] ) ? sanitize_text_field( $params['date'] ) : '';
			$slots = isset( $params['slots'] ) && ! empty( $params['slots'] ) ? sanitize_text_field( stripslashes( $params['slots'] ) ) : '';
			$staff_id = isset( $params['staff_id'] ) && ! empty( $params['staff_id'] ) ? sanitize_text_field( $params['staff_id'] ) : '';
		
			$general_settings = get_option( 'bookify_general_settings' );
			$get_time_format = is_array( $general_settings ) && isset( $general_settings['DefaultTimeFormat'] ) ? sanitize_text_field( $general_settings['DefaultTimeFormat'] ) : '12-hour';
		
			if ( '12-hour' == $get_time_format ) {
				$time_format = 'h:i A';
			} else {
				$time_format = 'H:i';
			}
		
			$slots = json_decode( $slots, true );
			$current_time = current_time('H:i');
			
			if ( $date === current_time('Y-m-d') ) {
				$slots = array_filter( $slots, function ( $slot ) use ( $current_time ) {
					list( $start_time, $end_time ) = explode( ' - ', $slot );
					$start_time_24hr = gmdate( 'H:i', strtotime( $start_time ) );
		
					return $start_time_24hr > $current_time;
				} );
			}

			$booked_slots = Bookify_Appointment_Models::bookify_get_appointments_by_date_staff( $date, $staff_id );

			$decoded_booked_slots = array();
			foreach ( $booked_slots as $slot ) {
				$decoded_slot = json_decode( $slot, true );
				if ( is_array( $decoded_slot ) ) {
					$decoded_booked_slots = array_merge( $decoded_booked_slots, $decoded_slot );
				}
			}

			$available_slots = array_values( array_diff( $slots, $decoded_booked_slots ) );
			$formatted_slots = array();
		
			foreach ( $available_slots as $available_slot ) {
				list( $start_time, $end_time ) = explode(' - ', $available_slot);
		
				$formatted_start_time = gmdate( $time_format, strtotime( $start_time ) );
				$formatted_end_time = gmdate( $time_format, strtotime( $end_time ) );
				$formatted_slots[] = $formatted_start_time . ' - ' . $formatted_end_time;
			}

			$args = array(
				'timeFormat' => $get_time_format,
				'available_slots' => $formatted_slots,
			);

			if ( class_exists('\BookifyPro\Bookify_Pro_Main') && defined( 'BOOKIFY_PRO_LICENCE_ACTIVATED' ) == true ) {
				$multiple_booking = get_user_meta( $staff_id, 'bookify_staff_mutiple_booking', true );
				$args['multipleBooking'] = ( $multiple_booking === 'true' || $multiple_booking === true || $multiple_booking === '1' || $multiple_booking === 1 ) ? 'true' : 'false';
			}
		
			return new WP_REST_Response( $args, 200 );
		}

		public function rest_add_appointments_data_callback( $request ) {

			$nonce = $request->get_header('X-WP-Nonce');
			if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
				return new WP_Error( 'rest_forbidden', __('Invalid nonce.', 'bookify'), array( 'status' => 403 ) );
			}

			$params = $request->get_json_params();

			$general_settings = get_option( 'bookify_general_settings');
			$default_appointment_status = is_array( $general_settings ) && isset( $general_settings['DefaultAppointmentStatus'] ) ? $general_settings['DefaultAppointmentStatus'] : 'Pending';

			$appointment_location = isset( $params['appointment_location'] ) && ! empty( $params['appointment_location'] ) ? sanitize_text_field( $params['appointment_location'] ) : 0;
			$appointment_service = isset( $params['appointment_service'] ) && ! empty( $params['appointment_service'] ) ? sanitize_text_field( $params['appointment_service'] ) : '';
			$appointment_staff = isset( $params['appointment_staff'] ) && ! empty( $params['appointment_staff'] ) ? sanitize_text_field( $params['appointment_staff'] ) : '';
			$appointment_date = isset( $params['appointment_date'] ) && ! empty( $params['appointment_date'] ) ? sanitize_text_field( $params['appointment_date'] ) : '';
			$appointment_duration = isset( $params['appointment_duration'] ) && ! empty( $params['appointment_duration'] ) ? sanitize_text_field( $params['appointment_duration'] ) : '';
			$appointment_price = isset( $params['appointment_price'] ) && ! empty( $params['appointment_price'] ) ? sanitize_text_field( $params['appointment_price'] ) : '';
			$customer_id = isset( $params['customer_id'] ) && ! empty( $params['customer_id'] ) ? sanitize_text_field( $params['customer_id'] ) : '';
			$appointment_status = isset( $params['appointment_status'] ) && ! empty( $params['appointment_status'] ) ? sanitize_text_field( $params['appointment_status'] ) : $default_appointment_status;
			$note = isset( $params['note'] ) && ! empty( $params['note'] ) ? sanitize_text_field( $params['note'] ) : '';
			$timezone = wp_timezone_string();

			if ( ! $appointment_service ||  ! $appointment_staff ||  ! $appointment_date || ! $appointment_duration || ! $appointment_price || ! $customer_id ) {
				return new WP_REST_Response(array(
					'success' => false,
					'message' => 'Please Fill the required fields!',
				), 200);
			}

			$appointment_data = array(
				'appointment_location' => $appointment_location,
				'appointment_service' => $appointment_service,
				'appointment_staff' => $appointment_staff,
				'appointment_date' => $appointment_date,
				'appointment_duration' => json_encode( explode( ',', $appointment_duration ) ),
				'appointment_price' => $appointment_price,
				'appointment_customer' => $customer_id,
				'appointment_created' => current_datetime()->format('Y-m-d H:i:s'),
				'appointment_status' => $appointment_status,
				'appointment_note' => $note,
			);

			$appointment_id = Bookify_Appointment_Models::bookify_add_appointment( $appointment_data );
			
			if ( ! is_wp_error( $appointment_id ) ) {
				bookify_add_appointments_meta( $appointment_id, 'timezone', $timezone );

				if ( class_exists('\BookifyPro\Bookify_Pro_Main') && defined( 'BOOKIFY_PRO_LICENCE_ACTIVATED' ) == true ) {
					Bookify_Pro_Helper::create_appointment_to_calendars( $appointment_id, $appointment_data, true );

					Bookify_Pro_Helper::appointment_zoom_meeting( $appointment_id, $appointment_data );
				}

				/**
				 * Action - Sends email on requested appointment.
				 * 
				 * @since 1.0
				**/
				do_action( 'bookify_appointment_requested_email', $appointment_id );

				return new WP_REST_Response(array(
					'success' => $appointment_id,
					'message' => 'Appointment has been added successfully!'
				), 200);
			} else {
				return new WP_REST_Response(array(
					'success' => false,
					'message' => 'Error while adding appointment!'
				), 200);
			}
		}

		public function rest_appointments_data_callback( $request ) {

			$page = $request->get_param('page');
			$pageSize = $request->get_param('pageSize');
			$search = $request->get_param('search');
			$is_staff = false;
			$current_staff_id = false;

			if ( is_user_logged_in() ) {
				$current_user = wp_get_current_user();

				if ( in_array( 'bookify-staff', (array) $current_user->roles ) && ( ! in_array( 'administrator', (array) $current_user->roles ) ) ) {
					$current_staff_id = $current_user->ID;
					$is_staff = true;
				}
			}

			$all_services = array();
			$all_locations = array();

			$apointment_data = Bookify_Appointment_Models::bookify_get_all_appointments_for_table( $current_staff_id );
			
			if ( class_exists( '\BookifyPro\Bookify_Pro_Main' ) && defined( 'BOOKIFY_PRO_LICENCE_ACTIVATED' ) == true ) {
				foreach ( $apointment_data as $key => $appointment ) {
					$zoom_links = bookify_get_appointments_meta( $appointment['appointment_id'], 'zoom_meeting_links' );
					if ( $zoom_links ) {
						$apointment_data[$key]['zoom_links'] = unserialize( $zoom_links );
					} else {
						$apointment_data[$key]['zoom_links'] = null;
					}
				}
				$all_locations = Bookify_Pro_Location_Models::bookify_get_all_locations();
			} else {
				$all_services = Bookify_Service_Models::bookify_get_all_services();
			}
			
			$all_customers = array();
			$bookify_customers = get_users(
				array(
					'role__in' => array( 'bookify-customer' )
				)
			);

			if ( $bookify_customers ) {
				foreach ($bookify_customers as $customer) {
					$all_customers[] = array(
						'id' => $customer->ID,
						'customer_name' => $customer->display_name,
					);
				}
			}
			
			$general_settings = get_option( 'bookify_general_settings' );
			$default_status = is_array( $general_settings ) && isset( $general_settings['DefaultAppointmentStatus'] ) ? $general_settings['DefaultAppointmentStatus'] : 'Pending';
			$date_format = is_array( $general_settings ) && isset( $general_settings['DefaultDateFormat'] ) ? $general_settings['DefaultDateFormat'] : 'DD/MM/YY';
			$time_format = is_array( $general_settings ) && isset( $general_settings['DefaultTimeFormat'] ) ? $general_settings['DefaultTimeFormat'] : '12-hour';
			$prior_booking_toggle = is_array( $general_settings ) && isset( $general_settings['DefaultPriorToBooking'] ) ? $general_settings['DefaultPriorToBooking'] : 'Disable';
			$prior_booking_time = is_array( $general_settings ) && isset( $general_settings['PriorTimeToBooking'] ) ? absint( $general_settings['PriorTimeToBooking'] ) : '3';
			$currency = is_array( $general_settings ) && isset( $general_settings['DefaultGeneralCurrencies'] ) ? $general_settings['DefaultGeneralCurrencies'] : 'USD';

			if ( ! empty( $search ) ) {
				$apointment_data = array_filter( $apointment_data, function ( $appointment ) use ( $search ) {
					$search_lower = strtolower( $search );
					return (
						strpos( strtolower( $appointment['appointment_date'] ), $search_lower ) !== false ||
						strpos( strtolower( $appointment['appointment_customer_name'] ), $search_lower ) !== false ||
						strpos( strtolower( $appointment['appointment_customer_email'] ), $search_lower ) !== false ||
						strpos( strtolower( $appointment['appointment_staff_name'] ), $search_lower ) !== false ||
						strpos( strtolower( $appointment['appointment_staff_email'] ), $search_lower ) !== false ||
						strpos( strtolower( $appointment['service_name'] ), $search_lower ) !== false ||
						strpos( strtolower( $appointment['appointment_price'] ), $search_lower ) !== false ||
						strpos( strtolower( $appointment['appointment_duration'] ), $search_lower ) !== false ||
						strpos( strtolower( $appointment['appointment_created'] ), $search_lower ) !== false ||
						strpos( strtolower( $appointment['appointment_status'] ), $search_lower ) !== false
					);
				});
			}

			$startIndex = ( $page - 1 ) * $pageSize;

			$paginatedData = array_slice($apointment_data, $startIndex, $pageSize);
			
			return new WP_REST_Response(array(
				'data' => $paginatedData,
				'total' => count($apointment_data),
				'locations' => $all_locations,
				'services' => $all_services,
				'customers' => $all_customers,
				'currency' => $currency,
				'default_status' => $default_status,
				'dateFormat' => $date_format,
				'timeFormat' => $time_format,
				'priorToggle' => $prior_booking_toggle,
				'priorTime' => $prior_booking_time,
				'is_staff' => $is_staff
			), 200);
		}
	}
	
	new Bookify_Appointments_Rest_API();
}
