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


if ( ! class_exists( 'OsStepsController' ) ) :


	class OsStepsController extends OsController {

		private $booking;

		function __construct() {
			parent::__construct();
			$this->action_access['customer'] = array_merge( $this->action_access['customer'], [] );
			$this->action_access['public']   = array_merge(
				$this->action_access['public'],
				[
					'start',
					'start_instant',
					'load_step',
					'reload_booking_form_summary_panel',
					'check_order_intent_bookable',
					'load_datepicker_month',
					'start_from_order_intent',
				] 
			);

			$this->views_folder          = LATEPOINT_VIEWS_ABSPATH . 'steps/';
			$this->vars['page_header']   = __( 'Appointments', 'latepoint' );
			$this->vars['breadcrumbs'][] = array(
				'label' => __( 'Appointments', 'latepoint' ),
				'link'  => OsRouterHelper::build_link(
					[
						'bookings',
						'pending_approval',
					] 
				),
			);
		}


		public function start_instant() {
			$atts = [];
			if ( ! empty( $this->params['selected_agent'] ) ) {
				$atts['selected_agent'] = sanitize_text_field( $this->params['selected_agent'] );
			}
			if ( ! empty( $this->params['selected_service'] ) ) {
				$atts['selected_service'] = sanitize_text_field( $this->params['selected_service'] );
			}
			if ( ! empty( $this->params['selected_location'] ) ) {
				$atts['selected_location'] = sanitize_text_field( $this->params['selected_location'] );
			}

			if ( ! empty( $this->params['hide_side_panel'] ) && $this->params['hide_side_panel'] == 'yes' ) {
				$atts['hide_side_panel'] = 'yes';
			}
			if ( ! empty( $this->params['hide_summary'] ) && $this->params['hide_summary'] == 'yes' ) {
				$atts['hide_summary'] = 'yes';
			}
			if ( ! empty( $this->params['background_pattern'] ) ) {
				$this->vars['background_pattern'] = sanitize_text_field( $this->params['background_pattern'] );
			}

			$this->vars['atts'] = $atts;
			$this->set_layout( 'clean' );
			$this->format_render( __FUNCTION__ );
		}

		public function load_datepicker_month() {
			OsStepsHelper::set_required_objects( $this->params );

			$target_date       = new OsWpDateTime( $this->params['target_date_string'] );
			$calendar_settings = [
				'layout'        => $this->params['calendar_layout'] ?? 'classic',
				'timezone_name' => $this->params['timezone_name'] ?? false,
			];

			$calendar_settings['earliest_possible_booking'] = OsSettingsHelper::get_earliest_possible_booking_restriction( OsStepsHelper::$booking_object->service_id ?? false );
			$calendar_settings['latest_possible_booking']   = OsSettingsHelper::get_latest_possible_booking_restriction( OsStepsHelper::$booking_object->service_id ?? false );

			$this->format_render(
				'partials/_monthly_calendar_days',
				[
					'target_date'       => $target_date,
					'calendar_settings' => $calendar_settings,
					'booking_request'   => \LatePoint\Misc\BookingRequest::create_from_booking_model( OsStepsHelper::$booking_object ),
				] 
			);
		}


		public function check_order_intent_bookable() {
			OsStepsHelper::set_required_objects( $this->params );
			if ( OsStepsHelper::$cart_object->order_id ) {
				// already converted, so we are good
				$this->send_json(
					[
						'status'  => LATEPOINT_STATUS_SUCCESS,
						'message' => __( 'Cart has already been converted to order', 'latepoint' ),
					] 
				);
			}
			$order_intent = OsOrderIntentHelper::create_or_update_order_intent( OsStepsHelper::$cart_object, OsStepsHelper::$restrictions, OsStepsHelper::$presets, '', OsStepsHelper::get_customer_object_id() );
			if ( $order_intent->is_bookable() ) {
				$this->send_json(
					[
						'status'  => LATEPOINT_STATUS_SUCCESS,
						'message' => __( 'Order intent can be converted to order', 'latepoint' ),
					] 
				);
			} else {
				$this->send_json(
					[
						'status'  => LATEPOINT_STATUS_ERROR,
						'message' => __( 'Selected booking slot is not available anymore. Please pick a different time slot.', 'latepoint' ),
					] 
				);
			}
		}

		function generate_timeslots_for_day() {
			OsStepsHelper::set_required_objects( $this->params );



			wp_send_json(
				[
					'status'  => LATEPOINT_STATUS_SUCCESS,
					'message' => '',
				] 
			);
		}


		function reload_booking_form_summary_panel() {
			OsStepsHelper::set_required_objects( $this->params );
			$this->vars['cart'] = OsStepsHelper::$cart_object;

			if ( OsStepsHelper::is_ready_for_summary() ) {
				$this->vars['current_step_code'] = $this->params['current_step_code'] ?? '';
				$this->vars['booking']           = OsStepsHelper::$booking_object;
				$this->vars['customer']          = OsStepsHelper::get_customer_object();
				$this->vars['active_cart_item']  = OsStepsHelper::$active_cart_item;

				if ( $this->get_return_format() == 'json' ) {
					$response_html = $this->render( $this->views_folder . 'partials/_booking_form_summary_panel', 'none' );
					wp_send_json(
						[
							'status'  => LATEPOINT_STATUS_SUCCESS,
							'message' => $response_html,
						] 
					);
					exit();
				} else {
					echo $this->render( $this->views_folder . 'partials/_booking_form_summary_panel', $this->get_layout() );
				}
			} else {
				wp_send_json(
					[
						'status'  => LATEPOINT_STATUS_SUCCESS,
						'message' => '',
					] 
				);
			}
		}


		public function start_from_order_intent() {
			$order_intent = OsOrderIntentHelper::get_order_intent_by_intent_key( $this->params['order_intent_key'] );

			if ( ! $order_intent->is_new_record() ) {
				$step_codes_to_preload = [];
				$steps                 = OsStepsHelper::get_steps();
				OsStepsHelper::set_required_objects( $this->params );

				if ( $order_intent->order_id ) {
					// if order is created - load it
					OsStepsHelper::load_order_object( $order_intent->order_id );
					$current_step_code = 'confirmation';
					$current_step      = $steps[ $current_step_code ];

					$this->vars['price_breakdown_rows'] = OsStepsHelper::$order_object->generate_price_breakdown_rows();

					$steps = [ 'confirmation' => $steps['confirmation'] ];


				} else {

					OsStepsHelper::set_cart_object_from_order_intent( $order_intent );
					$current_step_code = 'verify';
					$current_step      = $steps[ $current_step_code ];


					foreach ( OsStepsHelper::$step_codes_in_order as $step_code ) {
						if ( $step_code == $current_step_code ) {
							break;
						} else {
							$step_codes_to_preload[] = $step_code;
						}
					}

					$this->vars['price_breakdown_rows'] = OsStepsHelper::$cart_object->generate_price_breakdown_rows();
					// order exists - only load confirmation step
					$this->vars['step_codes_to_preload'] = $step_codes_to_preload;

				}

				$this->vars['cart']          = OsStepsHelper::$cart_object;
				$this->vars['show_next_btn'] = OsStepsHelper::can_step_show_next_btn( $current_step_code );
				$this->vars['show_prev_btn'] = OsStepsHelper::can_step_show_prev_btn( $current_step_code );
				$this->vars['all_steps']     = OsStepsHelper::get_steps( true );
				$this->vars['steps']         = $steps;
				$this->vars['current_step']  = $current_step;

				$this->vars['current_step_code']      = $current_step_code;
				$this->vars['booking']                = OsStepsHelper::$booking_object;
				$this->vars['customer']               = OsStepsHelper::get_customer_object();
				$this->vars['active_cart_item']       = OsStepsHelper::$active_cart_item;
				$this->vars['restrictions']           = OsStepsHelper::$restrictions;
				$this->vars['presets']                = OsStepsHelper::$presets;
				$this->vars['booking_element_type']   = 'lightbox';
				$this->vars['booking_element_styles'] = [];





				$this->set_layout( 'none' );

				$this->format_render( 'start', array(), array( 'lightbox_class' => '' ) );
			} else {
				$this->send_json(
					array(
						'status'  => LATEPOINT_STATUS_ERROR,
						'message' => __( 'Invalid order intent key', 'latepoint' ),
					) 
				);
			}
		}

		public function start( array $custom_restrictions = [], array $custom_presets = [], array $booking_element_styles = [], bool $output = true, string $booking_element_type = 'lightbox' ) {
			$merged_params = $this->params;

			if ( ! empty( $custom_restrictions ) ) {
				$merged_params['restrictions'] = $custom_restrictions;
			}
			if ( ! empty( $custom_presets ) ) {
				$merged_params['presets'] = $custom_presets;
			}
			if ( ! empty( $this->params['booking_element_type'] ) ) {
				$booking_element_type = $this->params['booking_element_type'];
			}


			if ( ! empty( $merged_params['booking_element_styles'] ) ) {
				$booking_element_styles = array_merge( $booking_element_styles, $merged_params['booking_element_styles'] );
			}

			// set early to check if it's converted or should be emptied
			OsStepsHelper::set_cart_object();
			if ( ! empty( OsStepsHelper::$cart_object->order_id ) ) {
				OsCartsHelper::reset_cart();
				OsStepsHelper::set_cart_object();
			}
			// clear cart if "shopping cart" feature is not enabled
			if ( ! OsCartsHelper::can_checkout_multiple_items() ) {
				OsStepsHelper::$cart_object->clear();
			}




			OsStepsHelper::set_required_objects( $merged_params );

			$steps = OsStepsHelper::get_steps();

			$current_step_code = OsStepsHelper::get_step_codes_in_order()[0];

			if ( OsStepsHelper::should_step_be_skipped( $current_step_code ) ) {
				$current_step_code = OsStepsHelper::get_next_step_code( $current_step_code );
			}
			// check if all booking steps have to be skipped, if so - it means the booking object is ready and we can add it to the cart
			$ready_to_add_to_cart = true;
			if ( OsStepsHelper::$active_cart_item->is_booking() ) {
				foreach ( $steps as $step_code => $step_object ) {
					$step_main_parent_code = explode( '__', $step_code );
					if ( ! empty( $step_main_parent_code[0] ) && $step_main_parent_code[0] == 'booking' ) {
						$ready_to_add_to_cart = false;
						break;
					}
				}
			}
			// looks like item is ready to be added to cart (because all necessary steps/presets where applied in a trigger element), add it to cart
			if ( $ready_to_add_to_cart ) {
				try {
					OsStepsHelper::add_current_item_to_cart();
				} catch ( Exception $e ) {
					$this->vars['booking'] = OsStepsHelper::$booking_object;
					if ( $output ) {
						$this->format_render( 'preset_slot_not_available' );
						return false;
					} else {
						return $this->format_render_return( 'preset_slot_not_available' );
					}
				}
			}
			$current_step = $steps[ $current_step_code ];

			$this->vars['cart']          = OsStepsHelper::$cart_object;
			$this->vars['show_next_btn'] = OsStepsHelper::can_step_show_next_btn( $current_step->code );
			$this->vars['show_prev_btn'] = OsStepsHelper::can_step_show_prev_btn( $current_step->code );
			$this->vars['all_steps']     = OsStepsHelper::get_steps( true );
			$this->vars['steps']         = $steps;
			$this->vars['current_step']  = $current_step;

			$this->vars['current_step_code']      = $current_step->code;
			$this->vars['booking']                = OsStepsHelper::$booking_object;
			$this->vars['customer']               = OsStepsHelper::get_customer_object();
			$this->vars['active_cart_item']       = OsStepsHelper::$active_cart_item;
			$this->vars['restrictions']           = OsStepsHelper::$restrictions;
			$this->vars['presets']                = OsStepsHelper::$presets;
			$this->vars['booking_element_type']   = $booking_element_type;
			$this->vars['booking_element_styles'] = $booking_element_styles;
			$this->vars['timezone_name']          = OsTimeHelper::get_timezone_name_from_session();

			$this->set_layout( 'none' );



			if ( $output ) {
				$this->format_render( __FUNCTION__, [], [ 'step' => $current_step->code ] );
			} else {
				return $this->format_render_return( __FUNCTION__, [], [ 'step' => $current_step->code ] );
			}
		}


		public function load_step() {
			OsStepsHelper::set_required_objects( $this->params );

			$current_step_code = OsStepsHelper::retrieve_step_code( $this->params['current_step_code'] );
			if ( empty( $current_step_code ) ) {
				return false;
			}

			$step_direction    = $this->params['step_direction'] ?? 'next';
			$step_code_to_load = false;
			switch ( $step_direction ) {
				case 'next':
					/**
					 * Process step by code
					 *
					 * @param {string} $step_code step code that will be processed
					 * @param {OsBookingModel} $booking booking object
					 * @param {array} $params array of params
					 *
					 * @since 5.0.0
					 * @hook latepoint_process_step
					 *
					 */
					do_action( 'latepoint_process_step', $current_step_code, OsStepsHelper::$booking_object, $this->params );
					$step_code_to_load = OsStepsHelper::get_next_step_code( $current_step_code );
					break;
				case 'prev':
					$step_code_to_load = OsStepsHelper::get_prev_step_code( $current_step_code );
					break;
				case 'specific':
					$step_code_to_load = OsStepsHelper::should_step_be_skipped( $current_step_code ) ? OsStepsHelper::get_next_step_code( $current_step_code ) : $current_step_code;
					break;
			}
			if ( $step_code_to_load ) {

				/**
				 * Load step by code
				 *
				 * @param {string} $step_code step code to load
				 * @param {string} $type type of return (json)
				 * @param {array} $params array of params
				 *
				 * @since 5.0.0
				 * @hook latepoint_load_step
				 *
				 */
				do_action( 'latepoint_load_step', $step_code_to_load, 'json', $this->params );
			}
		}
	}


endif;
