<?php

namespace Bookify\Controllers\REST;

use WP_REST_Response;
use WP_User_Query;
use WP_Error;
use Bookify\Models\Bookify_Service_Models;
use Bookify\Models\Bookify_Appointment_Models;
use BookifyPro\Models\Bookify_Pro_Location_Models;

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

if ( ! class_exists( 'Bookify_Calendar_Rest_API' ) ) {

	class Bookify_Calendar_Rest_API {

		public function __construct() {

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

		public function rest_api_calendar() {

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

			register_rest_route('bookify/v1', '/staffs-by-service', array(
				'methods'               => 'POST',
				'callback'              => array( $this, 'rest_staffs_by_service_data_callback' ),
				'permission_callback'   => array( $this, 'verify_nonce_and_permissions' )
			)); 

			register_rest_route('bookify/v1', '/dates-by-staff', array(
				'methods'               => 'POST',
				'callback'              => array( $this, 'rest_dates_by_staff_data_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_dates_by_staff_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();
			
			$staff_id = isset( $params['staff_id'] ) && ! empty( $params['staff_id'] ) ? sanitize_text_field( $params['staff_id'] ) : '';
			$service_id = isset( $params['service_id'] ) && ! empty( $params['service_id'] ) ? sanitize_text_field( $params['service_id'] ) : '';
			$location_id = isset( $params['location_id'] ) && ! empty( $params['location_id'] ) ? sanitize_text_field( $params['location_id'] ) : '';
			$services_attr = isset( $params['services'] ) && ! empty( $params['services'] ) ? $params['services'] : '';
			$staffs_attr = isset( $params['staffs'] ) && ! empty( $params['staffs'] ) ? $params['staffs'] : '';

			$servicePrice = '';
			$serviceName = '';

			if ( ! $staff_id || 'none' === $staff_id ) {
				return new WP_REST_Response(array(
					'dates' => array(),
					'special' => array(),
					'holidays' => array(),
				), 200);
			} 

			if ( ! empty( $services_attr ) && ! in_array( 'all', (array) $services_attr, true ) ) {
				$allowed_services = is_array( $services_attr ) ? $services_attr : explode( ',', $services_attr );
				$allowed_services = array_map( 'sanitize_text_field', $allowed_services );
				if ( $service_id && ! in_array( $service_id, $allowed_services, true ) ) {
					return new WP_REST_Response(array(
						'dates' => array(),
						'special' => array(),
						'holidays' => array(),
					), 200);
				}
			}

			if ( ! empty( $staffs_attr ) && ! in_array( 'all', (array) $staffs_attr, true ) ) {
				$allowed_staffs = is_array( $staffs_attr ) ? $staffs_attr : explode( ',', $staffs_attr );
				$allowed_staffs = array_map( 'sanitize_text_field', $allowed_staffs );
				if ( $staff_id && ! in_array( $staff_id, $allowed_staffs, true ) ) {
					return new WP_REST_Response(array(
						'dates' => array(),
						'special' => array(),
						'holidays' => array(),
					), 200);
				}
			}

			if ( $location_id && $service_id ) {
				$location_services = Bookify_Service_Models::bookify_get_all_services_by_location( $location_id );
				$service_ids = array();
				if ( $location_services ) {
					foreach ( $location_services as $service ) {
						$service_ids[] = (string) $service['id'];
					}
				}
				if ( ! in_array( (string) $service_id, $service_ids, true ) ) {
					return new WP_REST_Response(array(
						'dates' => array(),
						'special' => array(),
						'holidays' => array(),
					), 200);
				}
			}

			$staff_data = get_userdata( $staff_id );
			$allowed_roles = array( 'bookify-staff', 'administrator' );
			if ( ! $staff_data || ! array_intersect( $allowed_roles, (array) $staff_data->roles ) ) {
				return new WP_REST_Response(array(
					'dates' => array(),
					'special' => array(),
					'holidays' => array(),
					'servicePrice' => $servicePrice,
					'serviceName' => $serviceName,
				), 200);
			}

			if ( $service_id ) {
				$services = get_user_meta( $staff_id, 'bookify_staff_services', true );
				$services = json_decode( $services, true );
				$service_data = Bookify_Service_Models::bookify_get_service_by_id( $service_id );
				if ( $services && $service_data && array_key_exists( $service_id, $services ) ) {
					$servicePrice = (float) $services[ $service_id ]['price'];
					$serviceName = !empty( $service_data['service_name'] ) ? $service_data['service_name'] : '';
				} else {
					return new WP_REST_Response(array(
						'dates' => array(),
						'special' => array(),
						'holidays' => array(),
						'servicePrice' => $servicePrice,
						'serviceName' => $serviceName,
					), 200);
				}
			}

			$timeslots = get_user_meta( $staff_id, 'bookify_staff_timeslots', true );
			$special_days = get_user_meta( $staff_id, 'bookify_staff_special_days_timeslots', true );
			$holidays = get_user_meta( $staff_id, 'bookify_staff_holidays', true );

			return new WP_REST_Response(array(
				'dates' => $timeslots,
				'special' => $special_days,
				'holidays' => $holidays,
				'servicePrice' => $servicePrice,
				'serviceName' => $serviceName,
			), 200);
		}

		public function rest_staffs_by_service_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();

			$location_id = isset( $params['location_id'] ) && ! empty( $params['location_id'] ) ? sanitize_text_field( $params['location_id'] ) : '';
		    $service_id = isset( $params['service_id'] ) && ! empty( $params['service_id'] ) ? sanitize_text_field( $params['service_id'] ) : '';
			$staff_id = isset( $params['staff_id'] ) && ! empty( $params['staff_id'] ) ? sanitize_text_field( $params['staff_id'] ) : '';
		
			if ( ! $service_id ) {
				return new WP_REST_Response(array(
					'staffs' => array(),
				), 200);
			}

			$filtered_location_services = array();

			if ( ! empty( $location_id ) && $location_id != 'all' ) {
				$location_services = Bookify_Service_Models::bookify_get_all_services_by_location( $location_id );
				if ( $location_services ) {
					foreach ( $location_services as $key => $value ) {
						$filtered_location_services[] = $value['id'];
					}
				}
			}
		
			$user_query = new WP_User_Query( 
				array(
					'role__in' => array( 'bookify-staff' ),
					'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
						array(
							'key'     => 'bookify_staff_services',
							'compare' => 'EXISTS',
						),
					),
				)
			);

			$users = $user_query->get_results();
			$filtered_users = array();

			$bookify_staffs = class_exists('\BookifyPro\Bookify_Pro_Main') && defined( 'BOOKIFY_PRO_LICENCE_ACTIVATED' ) == true ? $users : [ $users[0] ];
		
			if ( ! empty( $bookify_staffs ) ) {
				foreach ( $bookify_staffs as $user ) {
					$services = get_user_meta( $user->ID, 'bookify_staff_services', true );
					if ( $services ) {
						$services = json_decode( $services, true );
						if ( isset( $services[ $service_id ] ) && $services[ $service_id ]['checked'] ) {
							if ( empty( $filtered_location_services ) || in_array( $service_id, $filtered_location_services ) ) {
								$filtered_users[] = $user;
							}
						}
					}
				}
			}

			if ( ! empty( $staff_id ) && $staff_id != 'all' ) {
				$staff_ids = explode( ',', $staff_id );
				$filtered_users = array_filter( $filtered_users, function( $user ) use ( $staff_ids ) {
					return in_array( $user->ID, $staff_ids );
				});
			}

		    $service_data = Bookify_Service_Models::bookify_get_service_by_id( $service_id );

			if ( ! empty( $filtered_users ) ) {
				$data_arrays = array();
				foreach ( $filtered_users as $user ) {
					$multiple_booking = get_user_meta( $user->ID, 'bookify_staff_mutiple_booking', true );
					$services = get_user_meta( $user->ID, 'bookify_staff_services', true );
					$services = json_decode( $services, true );
					$data_arrays[] = array(
						'staff_id' => $user->data->ID,
						'staff_name' => $user->data->display_name,
						'staff_email' => $user->data->user_email,
						'staff_img' => get_user_meta( $user->ID, 'bookify_staff_img', true ),
						'service_price' => (float) $services[ $service_id ]['price'],
						'mulitple_booking' => ( $multiple_booking === 'true' || $multiple_booking === true || $multiple_booking === '1' || $multiple_booking === 1 ) ? 'true' : 'false',
						'service_name'   => !empty( $service_data['service_name'] ) ? $service_data['service_name'] : ''
					);
				}

				return new WP_REST_Response(array(
					'staffs' => $data_arrays,
				), 200);
			} else {
				return new WP_REST_Response(array(
					'staffs' => array(),
				), 200);
			}
		}
		

		public function rest_calendar_data_callback( $request ) {

			$searchStaff = $request->get_param('staff') ? sanitize_text_field( $request->get_param('staff') ) : '';

			$general_settings = get_option( 'bookify_general_settings');
			$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';
			$default_status = is_array( $general_settings ) && isset( $general_settings['DefaultAppointmentStatus'] ) ? $general_settings['DefaultAppointmentStatus'] : 'Pending';

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

			if ( class_exists( '\BookifyPro\Bookify_Pro_Main' ) && defined( 'BOOKIFY_PRO_LICENCE_ACTIVATED' ) == true ) {
				$all_locations = Bookify_Pro_Location_Models::bookify_get_all_locations();
			} else {
				$all_services = Bookify_Service_Models::bookify_get_all_services();
			}

			$all_staffs = array();
			$bookify_staffs = get_users(
				array(
					'role' => array( 'bookify-staff' )
				)
			);

			if ( $bookify_staffs ) {
				foreach ($bookify_staffs as $staff) {
					$all_staffs[] = array(
						'id' => $staff->ID,
						'staff_name' => $staff->display_name,
					);
				}
			}

			$all_customers = array();
			$bookify_customers = get_users(
				array(
					'role' => array( 'bookify-customer' )
				)
			);

			if ( $bookify_customers ) {
				foreach ($bookify_customers as $customer) {
					$all_customers[] = array(
						'id' => $customer->ID,
						'customer_name' => $customer->display_name,
					);
				}
			}

			$is_staff = false;
			$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 ) ) {
					$staff_id = $current_user->ID;
					$is_staff = true;
				} else {
					$staff_id = $searchStaff;
				}
			}

			$calender_data = Bookify_Appointment_Models::bookify_get_all_appointments_for_calender( $staff_id );

			foreach ( $calender_data as &$appointment ) {
				$customer_id = $appointment['appointment_customer'];
				$customer = get_user_by( 'ID', $customer_id );
				if ( $customer ) {
					$appointment['customer_name'] = ucwords( $customer->display_name );
				} else {
					$appointment['customer_name'] = 'Guest';
				}
			}

			return new WP_REST_Response(array(
				'calender_data' => $calender_data,
				'dateFormat' => $date_format,
				'timeFormat' => $time_format,
				'priorToggle' => $prior_booking_toggle,
				'priorTime' => $prior_booking_time,
				'staffs' => $all_staffs,
				'locations' => $all_locations,
				'services' => $all_services,
				'customers' => $all_customers,
				'defaultAppointmentStatus' => $default_status,
				'is_staff' => $is_staff
			), 200);
		}
	}

	new Bookify_Calendar_Rest_API();

}
