<?php
namespace Bookify\Controllers\REST;

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

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

if ( ! class_exists( 'Bookify_Frontend_Rest_API' ) ) {

	class Bookify_Frontend_Rest_API {

		public function __construct() {

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

		public function rest_api_frontend() { 

			register_rest_route('bookify/frontend/v1', '/get-services', array(
				'methods'               => 'GET',
				'callback'              => array( $this, 'get_services' ),
				'permission_callback'   => array( $this, 'nonce_authentication' )
			)); 

			register_rest_route('bookify/frontend/v1', '/get-appointments', array(
				'methods'               => 'GET',
				'callback'              => array( $this, 'get_appointments_by_current_user' ),
				'permission_callback'   => array( $this, 'nonce_authentication' )
			));

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

			register_rest_route('bookify/frontend/v1', '/appointment-status', array(
				'methods'               => 'POST',
				'callback'              => array( $this, 'appointment_status_change' ),
				'permission_callback'   => array( $this, 'nonce_authentication' )
			));

			register_rest_route('bookify/frontend/v1', '/get-services-by-location', array(
				'methods'               => 'POST',
				'callback'              => array( $this, 'get_services_by_location_callback' ),
				'permission_callback'   => array( $this, 'nonce_authentication' )
			));

			register_rest_route('bookify/frontend/v1', '/check-validation', array(
				'methods'               => 'POST',
				'callback'              => array( $this, 'rest_check_validation_callback' ),
				'permission_callback'   => array( $this, 'nonce_authentication' )
			));
		}

		public function nonce_authentication( $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 get_services_by_location_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'] ) : '';
			$services = isset( $params['services'] ) && ! empty( $params['services'] ) ? rest_sanitize_array( $params['services'] ) : 'all';			

			$all_services = Bookify_Service_Models::bookify_get_all_categorizedservices_by_location( $location_id );

			if ( ! in_array( 'all', $services ) ) {
				$filtered_services = array();
				foreach ( $all_services as $service ) {
					$filtered_category_services = array();
					if ( in_array( $service['service_id'], $services ) ) {
						$filtered_services[] = $service;
					}
				}
				$all_services = $filtered_services;
			}
			$all_services = Bookify_Helper::bookify_services_sort( $all_services );

			return new WP_REST_Response( array(
				'services' => $all_services,
			), 200 );
		}

		public function appointment_status_change( $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 cancellation!',
				), 200);
			};

			$data = array(
				'appointment_status' => 'Cancelled'
			);

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

			if ( $result ) {

				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 );
				}

				bookify_delete_appointments_meta( $appointment_id, 'zoom_meeting_links' );

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

		public function get_appointments_by_current_user( $request ) {
			if ( is_user_logged_in() ) {
				$user = wp_get_current_user();

				$page = $request->get_param('page');
				$pageSize = $request->get_param('pageSize');

				$apointment_data = Bookify_Appointment_Models::bookify_get_all_appointments_frontend_by_customer( $user->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;
						}
					}
				}

				if ( $apointment_data ) {
					foreach ( $apointment_data as &$appointment ) {
						$bookify_staff = get_user_by( 'ID', $appointment['appointment_staff'] );
						$bookify_staff_name = $bookify_staff->display_name;
						$bookify_staff_img = get_user_meta( $bookify_staff->ID, 'bookify_staff_img', true );
						$bookify_staff_email = $bookify_staff->user_email;
						$appointment['appointment_staff_name'] = $bookify_staff_name;
						$appointment['appointment_staff_img'] = $bookify_staff_img;
						$appointment['appointment_staff_email'] = $bookify_staff_email;
					}
				}

				$general_settings = get_option( 'bookify_general_settings' );
				$currency = is_array( $general_settings ) && isset( $general_settings['DefaultGeneralCurrencies'] ) ? $general_settings['DefaultGeneralCurrencies'] : 'USD';
				$timeFormat = is_array( $general_settings ) && isset( $general_settings['DefaultTimeFormat'] ) ? $general_settings['DefaultTimeFormat'] : '12-hour'; 

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

				$paginatedData = array_slice($apointment_data, $startIndex, $pageSize);

				return new WP_REST_Response(array(
					'data' => $paginatedData,
					'total' => count($apointment_data),
					'currency' => $currency,
					'timeFormat' => $timeFormat,
				), 200);


			}
		}

		public function get_services( $request ) {

			$services = $request->get_header('Services');
			$services = explode( ',', $services );

			$categories = Bookify_Category_Models::bookify_get_all_service_categories();
			
			if( ! empty( $services ) ) {
				$services = Bookify_Service_Models::bookify_get_attr_services( $services );
			} else {
				$services = Bookify_Service_Models::bookify_get_all_services();
			}

			return new WP_REST_Response(array(
				'services' => $services,
				'categories' => $categories,
			), 200);
		}

		public function add_appointment( $request ) {

			$params = $request->get_json_params();

			$location_id = isset( $params['location_id'] ) && ! empty( $params['location_id'] ) ? sanitize_text_field( $params['location_id'] ) : 0;
			$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'] ) : '';
			$date = isset( $params['date'] ) && ! empty( $params['date'] ) ? sanitize_text_field( $params['date'] ) : '';
			$duration = isset( $params['slot'] ) && ! empty( $params['slot'] ) ? rest_sanitize_array( $params['slot'] ) : '';
			$customer_id = isset( $params['customer_id'] ) ? sanitize_text_field( $params['customer_id'] ) : '';
			$fname = isset( $params['first_name'] ) && ! empty( $params['first_name'] ) ? sanitize_text_field( $params['first_name'] ) : '';
			$lname = isset( $params['last_name'] ) && ! empty( $params['last_name'] ) ? sanitize_text_field( $params['last_name'] ) : '';
			$email = isset( $params['email'] ) && ! empty( $params['email'] ) ? sanitize_email( $params['email'] ) : '';
			$phone = isset( $params['phone'] ) && ! empty( $params['phone'] ) ? sanitize_text_field( $params['phone'] ) : '';
			$note = isset( $params['note'] ) && ! empty( $params['note'] ) ? sanitize_text_field( $params['note'] ) : '';
			$gateway = isset( $params['gateway'] ) && ! empty( $params['gateway'] ) ? sanitize_text_field( ucwords( $params['gateway'] ) ) : 'on-site';
			$total = isset( $params['total'] ) && ! empty( $params['total'] ) ? sanitize_text_field( $params['total'] ) : 0;
			$paidAmount = isset( $params['paidAmount'] ) && ! empty( $params['paidAmount'] ) ? sanitize_text_field( $params['paidAmount'] ) : false;
			$timezone = isset( $params['timezone'] ) && ! empty( $params['timezone'] ) ? sanitize_text_field( $params['timezone'] ) : '';

			if ( ! $service_id ||  ! $staff_id ||  ! $date || ! $duration || ! $fname || ! $lname || ! $email || ! $phone ) {
				return new WP_Error( 'missing_required_fields', 'Required data is missing!', array( 'status' => 400 ) );
			}

			if ( class_exists('\BookifyPro\Bookify_Pro_Main') && defined( 'BOOKIFY_PRO_LICENCE_ACTIVATED' ) == true && ! $location_id ) {
				return new WP_Error( 'missing_required_fields', 'Required data is missing!', array( 'status' => 400 ) );
			}
			
			$general_settings = get_option( 'bookify_general_settings');
			$status = is_array( $general_settings ) && isset( $general_settings['DefaultAppointmentStatus'] ) ? $general_settings['DefaultAppointmentStatus'] : 'Pending';
			$max_limit_per_day = is_array( $general_settings ) && isset( $general_settings['MaxBookingsPerEmailPerDay'] ) ? intval( $general_settings['MaxBookingsPerEmailPerDay'] ) : 5;
			$users_can_book = is_array( $general_settings ) && isset( $general_settings['usersCanBook'] ) ? $general_settings['usersCanBook'] : 'registerAfterBook';

			$appointment_count = Bookify_Helper::get_appointment_count_per_day_by_customer( $email );

			if ( $appointment_count >= $max_limit_per_day ) {
				return new WP_Error( 'max_limit_reached', 'You have reached the daily booking limit.', array( 'status' => 400 ) );
			}

			if ( empty( $customer_id ) ) {

				$existing_user = email_exists( $email );

				if ( $existing_user ) { 
					if ( $users_can_book == 'guestBooking' ) {
						$customer_id = $existing_user;
					} else {
						return new WP_Error( 'email_exists', 'Email already exists. Please log in first.', array( 'status' => 400 ) );
					}
				} else {
					$password = Bookify_Helper::generate_strong_password();

					$bookify_customer_arg = array(
						'user_pass'  => $password,
						'user_login' => $email,
						'user_email' => $email,
						'first_name' => $fname,
						'last_name'  => $lname,
						'role'       => 'bookify-customer',
						'meta_input' => array(
							'bookify_customer_phone' => $phone,
						)
					);

					$customer_id = wp_insert_user( $bookify_customer_arg );

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

					$body = __('Your account has been created. Below are your login details:', 'bookify');
					Bookify_Helper::new_customer_notification( $customer_id, $body, $password );

					if ( $users_can_book != 'guestBooking' ) {
						wp_signon( array(
							'user_login'    => $email,
							'user_password' => $password,
							'remember'      => true,
						), false );
					}
				}
			}

			if ( ! metadata_exists( 'user', $customer_id, 'bookify_customer_phone' )) {
				update_user_meta( $customer_id, 'bookify_customer_phone', $phone );
			}

			/**
			 * Filter: To change the status of Bookify appoinemnt before creating.
			 * 
			 * @param: string $status - Values are: Pending, Confirmed, Completed, Delayed, On Hold, Canclled
			 * @param: array $data - The $_POST data.
			 * 
			 * @since 1.0.4 
			 */
			$status = apply_filters( 'bookify_appointment_status_change', $status, $data );

			$appointment_data = array(
				'appointment_location' => $location_id,
				'appointment_service' => $service_id,
				'appointment_staff' => $staff_id,
				'appointment_date' => $date,
				'appointment_duration' => json_encode( $duration ),
				'appointment_price' => $total,
				'appointment_customer' => $customer_id,
				'appointment_created' => current_datetime()->format('Y-m-d H:i:s'),
				'appointment_status' => $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 );

					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 );
				
				if ( 'On-site' != $gateway ) {
					$dueAmount = $total - $paidAmount;
					
					/**
					 * Filter: To change the status of Bookify payment before creating.
					 * 
					 * @param: string $status - Values are: Pending, , Paid, Partially Paid
					 * @param: int $appointment_id - The appointment id which was created
					 * @param: array $data - The $_POST data.
					 * 
					 * @since 1.0.4 
					 */
					$payment_status = apply_filters( 'bookify_payment_status_change', 'Paid', $appointment_id, $data );

					$args = array(
						'appointment_id' => $appointment_id,
						'payment_method' => $gateway,
						'payment_total' => $total,
						'payment_paid' => $paidAmount,
						'payment_due' => abs( $dueAmount ),
						'payment_status' => $payment_status,
					);

					$payment_id = Bookify_Payment_Models::bookify_add_payment( $args );

					if ( ! is_wp_error( $payment_id ) ) {
						return new WP_REST_Response(array(
							'success' => true,
							'message' => 'Payment has been created successfully!',
							'appointment_id' => $appointment_id
						), 200);
					} else {
						return new WP_Error( 'unable_adding_payment', 'Error while adding payment!.', array( 'status' => 400 ) );
					}
				} else {
					return new WP_REST_Response(array(
						'success' => true,
						'message' => 'Appointment has been created successfully!',
						'appointment_id' => $appointment_id
					), 200);
				}
			} else {
				return new WP_Error( 'unable_adding_appointment', 'Error while adding appointment!.', array( 'status' => 400 ) );
			}
		}

		public function rest_check_validation_callback( $request ) {

            $data = $request->get_json_params();

            $location_id = isset( $data['location_id'] ) && ! empty( $data['location_id'] ) ? sanitize_text_field( $data['location_id'] ) : 0;
			$service_id = isset( $data['service_id'] ) && ! empty( $data['service_id'] ) ? sanitize_text_field( $data['service_id'] ) : '';
			$staff_id = isset( $data['staff_id'] ) && ! empty( $data['staff_id'] ) ? sanitize_text_field( $data['staff_id'] ) : '';
			$date = isset( $data['date'] ) && ! empty( $data['date'] ) ? sanitize_text_field( $data['date'] ) : '';
			$duration = isset( $data['slot'] ) && ! empty( $data['slot'] ) ? rest_sanitize_array( $data['slot'] ) : '';
			$customer_id = isset( $data['customer_id'] ) ? sanitize_text_field( $data['customer_id'] ) : '';
			$fname = isset( $data['first_name'] ) && ! empty( $data['first_name'] ) ? sanitize_text_field( $data['first_name'] ) : '';
			$lname = isset( $data['last_name'] ) && ! empty( $data['last_name'] ) ? sanitize_text_field( $data['last_name'] ) : '';
			$email = isset( $data['email'] ) && ! empty( $data['email'] ) ? sanitize_email( $data['email'] ) : '';
			$phone = isset( $data['phone'] ) && ! empty( $data['phone'] ) ? sanitize_text_field( $data['phone'] ) : '';
			$note = isset( $data['note'] ) && ! empty( $data['note'] ) ? sanitize_text_field( $data['note'] ) : '';

			if ( ! $service_id ||  ! $staff_id ||  ! $date || ! $duration || ! $fname || ! $lname || ! $email || ! $phone ) {
				return new WP_Error( 'missing_required_fields', 'Required data is missing!', array( 'status' => 400 ) );
			}

			if ( class_exists('\BookifyPro\Bookify_Pro_Main') && ! $location_id ) {
				return new WP_Error( 'missing_required_fields', 'Required data is missing!', array( 'status' => 400 ) );
			}
			
			$general_settings = get_option( 'bookify_general_settings');
			$status = is_array( $general_settings ) && isset( $general_settings['DefaultAppointmentStatus'] ) ? $general_settings['DefaultAppointmentStatus'] : 'Pending';

			$staff_services = get_user_meta( $staff_id, 'bookify_staff_services', true );
			$staff_services = json_decode( $staff_services );

			if ( empty( $staff_services->$service_id->price ) ) {
				return new WP_Error( 'price_not_defined', 'Service price is not defined.', array( 'status' => 400 ) );
			}

            if ( empty( $customer_id ) ) {

				if ( email_exists( $email ) ) {
					return new WP_Error( 'email_exists', 'Email already exists. Please log in first.', array( 'status' => 400 ) );
				}
			}

            return new WP_REST_Response(array(
                'success' => true,
            ), 200);

        }
	}

	new Bookify_Frontend_Rest_API();

}
