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


if ( ! class_exists( 'OsDashboardController' ) ) :


	class OsDashboardController extends OsController {

		private $booking;


		function __construct() {
			parent::__construct();

			$this->views_folder        = LATEPOINT_VIEWS_ABSPATH . 'dashboard/';
			$this->vars['page_header'] = __( 'Dashboard', 'latepoint' );
		}


		public function pro_agents() {
		}

		/*
			Index
		*/

		public function index() {
			$this->vars['page_header'] = false;

			ob_start();
			$this->widget_bookings_and_availability_timeline();
			$this->vars['widget_bookings_and_availability_timeline'] = ob_get_clean();

			ob_start();
			$this->widget_daily_bookings_chart();
			$this->vars['widget_daily_bookings_chart'] = ob_get_clean();

			ob_start();
			$this->widget_upcoming_appointments( 3 );
			$this->vars['widget_upcoming_appointments'] = ob_get_clean();

			$this->set_layout( 'admin' );
			$this->format_render( __FUNCTION__ );
		}

		public function widget_upcoming_appointments( $limit = 3 ) {
			$agents    = new OsAgentModel();
			$services  = new OsServiceModel();
			$bookings  = new OsBookingModel();
			$locations = new OsLocationModel();

			$selected_agent_id    = isset( $this->params['agent_id'] ) ? OsAuthHelper::get_current_user()->check_if_allowed_record_id( $this->params['agent_id'], 'agent' ) : false;
			$selected_service_id  = isset( $this->params['service_id'] ) ? OsAuthHelper::get_current_user()->check_if_allowed_record_id( $this->params['service_id'], 'service' ) : false;
			$selected_location_id = isset( $this->params['location_id'] ) ? OsAuthHelper::get_current_user()->check_if_allowed_record_id( $this->params['location_id'], 'location' ) : false;

			$this->vars['upcoming_bookings'] = $bookings->get_upcoming_bookings( $selected_agent_id, false, $selected_service_id, $selected_location_id, $limit );

			$this->vars['agents']    = $agents->should_be_active()->filter_allowed_records()->get_results_as_models();
			$this->vars['services']  = $services->should_be_active()->filter_allowed_records()->get_results_as_models();
			$this->vars['locations'] = $locations->should_be_active()->filter_allowed_records()->get_results_as_models();

			$this->vars['selected_agent_id']    = $selected_agent_id;
			$this->vars['selected_service_id']  = $selected_service_id;
			$this->vars['selected_location_id'] = $selected_location_id;


			$this->set_layout( 'none' );
			$this->format_render( __FUNCTION__ );
		}



		public function widget_daily_bookings_chart( $date_from = false, $date_to = false ) {
			if ( $date_from == false ) {
				$date_from = isset( $this->params['date_from'] ) ? OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->params['date_from'] ) : new OsWpDateTime( '-1 week' );
			}
			if ( $date_to == false ) {
				$date_to = isset( $this->params['date_to'] ) ? OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->params['date_to'] ) : new OsWpDateTime( 'now' );
			}


			$filter = new \LatePoint\Misc\Filter();
			$filter = OsRolesHelper::filter_allowed_records_from_arguments_or_filter( $filter );

			if ( ! empty( $this->params['agent_id'] ) ) {
				$filter->agent_id = $this->params['agent_id'];
			}
			if ( ! empty( $this->params['service_id'] ) ) {
				$filter->service_id = $this->params['service_id'];
			}
			if ( ! empty( $this->params['location_id'] ) ) {
				$filter->location_id = $this->params['location_id'];
			}

			if ( ! OsRolesHelper::are_all_records_allowed() ) {
				if ( ! OsRolesHelper::are_all_records_allowed( 'agent' ) ) {
					$agent_id = OsRolesHelper::get_allowed_records( 'agent' );
				}
			}



			$daily_bookings = OsBookingHelper::get_total_bookings_per_day_for_period( $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter );

			$daily_chart_data = [];
			// fill data array with all the days
			for ( $day_date = clone $date_from; $day_date <= $date_to; $day_date->modify( '+1 day' ) ) {
				$daily_chart_data[ OsTimeHelper::get_nice_date_with_optional_year( $day_date->format( 'Y-m-d' ), false, true ) ] = 0;
			}
			// update the days with count of bookings
			foreach ( $daily_bookings as $bookings_for_day ) {
				$daily_chart_data[ OsTimeHelper::get_nice_date_with_optional_year( gmdate( 'Y-m-d', strtotime( $bookings_for_day->start_date ) ), false, true ) ] = $bookings_for_day->bookings_per_day;
			}

			$this->vars['total_bookings']      = OsBookingHelper::get_stat_for_period( 'bookings', $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter );
			$this->vars['total_price']         = OsBookingHelper::get_stat_for_period( 'price', $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter );
			$this->vars['total_duration']      = OsBookingHelper::get_stat_for_period( 'duration', $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter );
			$this->vars['total_new_customers'] = OsBookingHelper::get_new_customer_stat_for_period( $date_from, $date_to, $filter );

			$day_difference = $date_from->diff( $date_to );
			$day_difference = ( $day_difference->d > 0 ) ? $day_difference->d : 1;

			$prev_date_from = clone $date_from;
			$prev_date_from->modify( '-' . $day_difference . ' days' );
			$prev_date_to = clone $date_to;
			$prev_date_to->modify( '-' . $day_difference . ' days' );

			$this->vars['prev_total_bookings']      = OsBookingHelper::get_stat_for_period( 'bookings', $prev_date_from->format( 'Y-m-d' ), $prev_date_to->format( 'Y-m-d' ), $filter );
			$this->vars['prev_total_price']         = OsBookingHelper::get_stat_for_period( 'price', $prev_date_from->format( 'Y-m-d' ), $prev_date_to->format( 'Y-m-d' ), $filter );
			$this->vars['prev_total_duration']      = OsBookingHelper::get_stat_for_period( 'duration', $prev_date_from->format( 'Y-m-d' ), $prev_date_to->format( 'Y-m-d' ), $filter );
			$this->vars['prev_total_new_customers'] = OsBookingHelper::get_new_customer_stat_for_period( $prev_date_from, $prev_date_to, $filter );


			$agents    = new OsAgentModel();
			$services  = new OsServiceModel();
			$locations = new OsLocationModel();

			$this->vars['agents']    = $agents->should_be_active()->filter_allowed_records()->get_results_as_models();
			$this->vars['services']  = $services->should_be_active()->filter_allowed_records()->get_results_as_models();
			$this->vars['locations'] = $locations->should_be_active()->filter_allowed_records()->get_results_as_models();

			$this->vars['filter'] = $filter;

			$this->vars['date_from'] = $date_from->format( 'Y-m-d' );
			$this->vars['date_to']   = $date_to->format( 'Y-m-d' );

			$this->vars['daily_bookings_chart_labels_string']      = implode( ',', array_keys( $daily_chart_data ) );
			$this->vars['daily_bookings_chart_data_values_string'] = implode( ',', array_values( $daily_chart_data ) );

			$pie_labels     = [];
			$pie_colors     = [];
			$pie_values     = [];
			$pie_chart_data = OsBookingHelper::get_stat_for_period( 'bookings', $date_from->format( 'Y-m-d' ), $date_to->format( 'Y-m-d' ), $filter, 'service_id' );
			foreach ( $pie_chart_data as $pie_data ) {
				$service      = new OsServiceModel( $pie_data['service_id'] );
				$pie_labels[] = $service->name;
				$pie_colors[] = $service->bg_color;
				$pie_values[] = $pie_data['stat'];
			}

			$this->vars['pie_chart_data'] = [
				'labels' => $pie_labels,
				'colors' => $pie_colors,
				'values' => $pie_values,
			];

			$this->vars['date_period_string'] = OsTimeHelper::format_date_with_locale( OsSettingsHelper::get_readable_date_format( true, true ), $date_from ) . ' - ' . OsTimeHelper::format_date_with_locale( OsSettingsHelper::get_readable_date_format( true, true ), $date_to );

			$this->set_layout( 'none' );
			$this->format_render( __FUNCTION__ );
		}



		public function widget_bookings_and_availability_timeline() {
			$target_date = isset( $this->params['date_from'] ) ? OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->params['date_from'] ) : new OsWpDateTime( 'now' );

			$services  = new OsServiceModel();
			$agents    = new OsAgentModel();
			$locations = new OsLocationModel();

			$agents_models    = $agents->should_be_active()->filter_allowed_records()->get_results_as_models();
			$services_models  = $services->should_be_active()->filter_allowed_records()->get_results_as_models();
			$locations_models = $locations->should_be_active()->filter_allowed_records()->get_results_as_models();

			$this->vars['services']  = $services_models;
			$this->vars['locations'] = $locations_models;
			$this->vars['agents']    = $agents_models;

			if ( $services_models && ! empty( $this->params['service_id'] ) ) {
				$selected_service = $services->load_by_id( $this->params['service_id'] );
			} else {
				$selected_service = false;
			}


			if ( $locations_models ) {
				// show all locations option if agent can only be present at one place - because it means he does not have overlapping appointments on the calendar
				$default_location_id  = OsSettingsHelper::is_on( 'one_location_at_time' ) ? false : $locations_models[0]->id;
				$selected_location_id = ! empty( $this->params['location_id'] ) ? $this->params['location_id'] : $default_location_id;
			} else {
				$selected_location_id = false;
			}

			$this->vars['selected_location']    = $selected_location_id ? new OsLocationModel( $selected_location_id ) : false;
			$this->vars['selected_location_id'] = $selected_location_id;

			$timeblock_interval  = OsSettingsHelper::get_default_timeblock_interval();
			$selected_service_id = ( $selected_service ) ? $selected_service->id : false;

			$this->vars['selected_service']    = $selected_service;
			$this->vars['selected_service_id'] = $selected_service_id;



			// we are using two separate booking requests because the calendar on top has to generate availability timeline,
			// which can only be generated if we know service to check for. The second booking request is used to retrieve
			// shared resources for all services and locations (unless specific location is selected)
			$availability_booking_request = new \LatePoint\Misc\BookingRequest( [ 'start_date' => $target_date->format( 'Y-m-d' ) ] );
			$general_booking_request      = new \LatePoint\Misc\BookingRequest( [ 'start_date' => $target_date->format( 'Y-m-d' ) ] );
			if ( $selected_location_id ) {
				$availability_booking_request->location_id = $selected_location_id;
				$general_booking_request->location_id      = $selected_location_id;
			}
			if ( $selected_service ) {
				$availability_booking_request->service_id = $selected_service->id;
				// TODO add capacity and duration select box and POST params if multiple durations in a service
				$availability_booking_request->duration = $selected_service->duration;
				$timeblock_interval                     = $selected_service->get_timeblock_interval();
			}

			if ( count( $agents_models ) == 1 ) {
				$availability_booking_request->agent_id = $agents_models[0]->id;
				$general_booking_request->agent_id      = $agents_models[0]->id;
			}

			$settings               = [ 'accessed_from_backend' => true ];
			$resources              = OsResourceHelper::get_resources_grouped_by_day( $general_booking_request, $target_date, $target_date, $settings );
			$availability_resources = OsResourceHelper::get_resources_grouped_by_day( $availability_booking_request, $target_date, $target_date, $settings );
			$work_boundaries        = OsResourceHelper::get_work_boundaries_for_resources( $resources[ $target_date->format( 'Y-m-d' ) ] );
			$work_total_minutes     = $work_boundaries->end_time - $work_boundaries->start_time;

			$this->vars['timeblock_interval'] = $timeblock_interval;

			$bookings                = [];
			$agent_work_time_periods = [];
			if ( $agents_models ) {
				foreach ( $agents_models as $agent ) {
					$agent_work_time_periods[ $agent->id ] = [];
					$args                                  = [ 'agent_id' => $agent->id ];
					if ( $selected_location_id ) {
						$args['location_id'] = $selected_location_id;
					}
					$args['status']         = OsCalendarHelper::get_booking_statuses_to_display_on_calendar();
					$args                   = OsRolesHelper::filter_allowed_records_from_arguments_or_filter( $args );
					$bookings[ $agent->id ] = OsBookingHelper::get_bookings_for_date( $target_date->format( 'Y-m-d' ), $args );
				}
				foreach ( $availability_resources[ $target_date->format( 'Y-m-d' ) ] as $resource ) {
					if ( isset( $agent_work_time_periods[ $resource->agent_id ] ) ) {
						$agent_work_time_periods[ $resource->agent_id ] = array_merge( $agent_work_time_periods[ $resource->agent_id ], $resource->work_time_periods );
					}
				}
			}


			$this->vars['agent_work_time_periods'] = $agent_work_time_periods;

			$this->vars['availability_booking_request'] = $availability_booking_request;
			$this->vars['general_booking_request']      = $general_booking_request;

			$agents_resources = [];
			foreach ( $agents_models as $agent ) {
				$agent_booking_request                     = clone $availability_booking_request;
				$agent_booking_request->agent_id           = $agent->id;
				$daily_resources                           = OsResourceHelper::get_resources_grouped_by_day( $agent_booking_request, $target_date, null, $settings );
				$agents_resources[ 'agent_' . $agent->id ] = $daily_resources[ $target_date->format( 'Y-m-d' ) ];
			}
			$this->vars['agents_resources']    = $agents_resources;
			$this->vars['timeline_boundaries'] = OsResourceHelper::get_work_boundaries_for_groups_of_resources( $agents_resources );

			$this->vars['work_total_minutes'] = $work_total_minutes;
			$this->vars['work_boundaries']    = $work_boundaries;
			$this->vars['show_day_info']      = OsAuthHelper::is_admin_logged_in();
			$this->vars['target_date_obj']    = $target_date;
			$this->vars['target_date']        = $target_date->format( 'Y-m-d' );
			$this->vars['target_date_string'] = OsTimeHelper::get_readable_date( $target_date );

			$this->vars['what_to_show'] = isset( $this->params['what_to_show'] ) ? $this->params['what_to_show'] : 'appointments';


			$today_date = new OsWpDateTime( 'today' );

			if ( $target_date->format( 'Y-m-d' ) == $today_date->format( 'Y-m-d' ) ) {
				$time_now            = OsTimeHelper::now_datetime_object();
				$time_now_in_minutes = OsTimeHelper::convert_datetime_to_minutes( $time_now );
				if ( ( $time_now_in_minutes <= $work_boundaries->end_time && $time_now_in_minutes >= $work_boundaries->start_time ) && $work_total_minutes > 0 ) {
					$this->vars['time_now_label'] = $time_now->format( OsTimeHelper::get_time_format() );
					// agents row with avatars and margin below - offset that needs to be accounted for when calculating "time now" indicator position
					$this->vars['time_now_indicator_left_offset'] = ( $time_now_in_minutes - $work_boundaries->start_time ) / $work_total_minutes * 100;
					$this->vars['show_today_indicator']           = true;
				} else {
					$this->vars['show_today_indicator'] = false;
				}
			} else {
				$this->vars['show_today_indicator'] = false;
			}

			$this->set_layout( 'none' );

			$this->format_render( __FUNCTION__ );
		}
	}

endif;
