<?php
namespace AcademyProTutorBooking;

use DateTime;
use DateTimeZone;

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

class Database {
	public static function init() {
		$self = new self();
		add_action( 'init', [ $self, 'create_academy_booking_post_type' ] );
		add_action( 'rest_api_init', [ $self, 'register_academy_booking_meta' ] );
		add_filter( 'rest_prepare_academy_booking', [ $self, 'restrict_meta_key_in_rest_api' ], 10, 3 );
		add_filter( 'rest_prepare_academy_booking', [ $self, 'decode_special_character' ], 10, 3 );
		add_filter( 'rest_prepare_academy_booking_category', [ $self, 'taxonomy_decode_special_character' ], 10, 3 );
		add_filter( 'rest_prepare_academy_booking_tag', [ $self, 'taxonomy_decode_special_character' ], 10, 3 );
		add_filter( 'rest_prepare_academy_booking', [ $self, 'add_course_price' ], 10, 3 );
		add_filter( 'rest_request_before_callbacks', [ $self, 'check_academy_booking_schedule' ], 10, 3 );
	}

	public function create_academy_booking_post_type() {
		$permalinks = Helper::get_permalink_structure();
		$post_type = 'academy_booking';
		$booking_page_id = \Academy\Helper::get_settings( 'tutor_booking_page' );
		$has_archive = get_post( $booking_page_id ) ? urldecode( get_page_uri( $booking_page_id ) ) : 'tutor-booking';
		register_post_type(
			$post_type,
			array(
				'labels'                => array(
					'name'                  => esc_html__( 'Tutor Booking', 'academy-pro' ),
					'singular_name'         => esc_html__( 'booking', 'academy-pro' ),
					'search_items'          => esc_html__( 'Search Tutor Booking', 'academy-pro' ),
					'parent_item_colon'     => esc_html__( 'Parent Tutor Booking:', 'academy-pro' ),
					'not_found'             => esc_html__( 'No booking found.', 'academy-pro' ),
					'not_found_in_trash'    => esc_html__( 'No booking found in Trash.', 'academy-pro' ),
					'archives'              => esc_html__( 'tutor booking archives', 'academy-pro' ),
				),
				'public'                => true,
				'publicly_queryable'    => true,
				'show_ui'               => false,
				'show_in_menu'          => false,
				'hierarchical'          => true,
				'rewrite'               => array( 'slug' => 'tutor-booking' ),
				'query_var'             => true,
				'has_archive'           => $has_archive,
				'rewrite'             => $permalinks['rewrite_slug'] ? array(
					'slug'       => $permalinks['rewrite_slug'],
					'with_front' => false,
					'feeds'      => true,
				) : false,
				'delete_with_user'      => false,
				'supports'              => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'custom-fields', 'comments', 'post-formats' ),
				'show_in_rest'          => true,
				'rest_base'             => $post_type,
				'rest_namespace'        => ACADEMY_PLUGIN_SLUG . '/v1',
				'rest_controller_class' => 'WP_REST_Posts_Controller',
				'capability_type'           => 'post',
				'capabilities'              => array(
					'edit_post'             => 'edit_academy_booking',
					'read_post'             => 'read_academy_booking',
					'delete_post'           => 'delete_academy_booking',
					'delete_posts'          => 'delete_academy_bookings',
					'edit_posts'            => 'edit_academy_bookings',
					'edit_others_posts'     => 'edit_others_academy_bookings',
					'publish_posts'         => 'publish_academy_bookings',
					'read_private_posts'    => 'read_private_academy_bookings',
					'create_posts'          => 'edit_academy_bookings',
				),
			)
		);

		register_taxonomy(
			$post_type . '_category',
			$post_type,
			array(
				'hierarchical'          => true,
				'query_var'             => true,
				'public'                => true,
				'show_ui'               => false,
				'show_admin_column'     => false,
				'_builtin'              => true,
				'capabilities'          => array(
					'manage_terms' => 'manage_categories',
					'edit_terms'   => 'edit_categories',
					'delete_terms' => 'delete_categories',
					'assign_terms' => 'assign_categories',
				),
				'show_in_rest'          => true,
				'rest_base'             => $post_type . '_category',
				'rest_namespace'        => ACADEMY_PLUGIN_SLUG . '/v1',
				'rest_controller_class' => 'WP_REST_Terms_Controller',
				'rewrite'               => array(
					'slug'         => $permalinks['category_rewrite_slug'],
					'with_front'   => false,
					'hierarchical' => true,
				),
			)
		);

		register_taxonomy(
			$post_type . '_tag',
			$post_type,
			array(
				'hierarchical'          => false,
				'query_var'             => true,
				'public'                => true,
				'show_ui'               => false,
				'show_admin_column'     => false,
				'_builtin'              => true,
				'capabilities'          => array(
					'manage_terms' => 'manage_post_tags',
					'edit_terms'   => 'edit_post_tags',
					'delete_terms' => 'delete_post_tags',
					'assign_terms' => 'assign_post_tags',
				),
				'show_in_rest'          => true,
				'rest_base'             => $post_type . '_tag',
				'rest_namespace'        => ACADEMY_PLUGIN_SLUG . '/v1',
				'rest_controller_class' => 'WP_REST_Terms_Controller',
				'rewrite'               => array(
					'slug'         => $permalinks['tag_rewrite_slug'],
					'with_front'   => false,
					'hierarchical' => true,
				),
			)
		);
	}

	public function register_academy_booking_meta() {
		$course_meta = [
			'_academy_booking_type'                     => 'string',
			'_academy_booking_product_id'               => 'integer',
			'_academy_booking_class_type'               => 'string',
			'_academy_booking_schedule_type'            => 'string',
			'_academy_booking_private_booked_info'      => 'string',
			'_academy_booking_schedule_time_zone'       => 'string',
			'_academy_booking_duration'                 => 'integer',
		];

		foreach ( $course_meta as $meta_key => $meta_value_type ) {
			register_meta(
				'post',
				$meta_key,
				array(
					'object_subtype' => 'academy_booking',
					'type'           => $meta_value_type,
					'single'         => true,
					'show_in_rest'   => true,
				)
			);
		}

		register_meta(
			'post',
			'_academy_booking_schedule_time',
			array(
				'object_subtype' => 'academy_booking',
				'type'           => 'object',
				'single'         => true,
				'show_in_rest'   => [
					'schema' => array(
						'type'       => 'object',
						'properties' => [
							'date' => array(
								'type' => 'string',
							),
							'start_time' => array(
								'type' => 'string',
							),
							'end_time'  => array(
								'type' => 'string',
							),
						],
					),
				],
			)
		);

		register_meta(
			'post',
			'_academy_booking_schedule_repeated_times',
			array(
				'object_subtype' => 'academy_booking',
				'type'           => 'array',
				'single'         => true,
				'show_in_rest'   => [
					'schema' => array(
						'items' => array(
							'type'       => 'object',
							'properties' => [
								'day'   => array(
									'type' => 'string',
								),
								'scheduleTimes' => array(
									'type' => 'array',
									'items' => array(
										'type' => 'object',
										'properties' => [
											'start_time' => array(
												'type' => 'string',
											),
											'end_time' => array(
												'type' => 'string',
											),
										]
									)
								)
							],
						),
					),
				],
			)
		);
	}

	public function restrict_meta_key_in_rest_api( $item, $post, $request ) {
		$author_data = get_userdata( $item->data['author'] );
		$item->data['author_name'] = $author_data->display_name;
		// Check if the user has permission to edit the post
		if ( ! current_user_can( 'edit_academy_booking', $post->ID ) ) {
			if ( isset( $item->data['meta']['_academy_booking_private_booked_info'] ) ) {
				unset( $item->data['meta']['_academy_booking_private_booked_info'] );
			}
		}

		return $item;
	}

	public function decode_special_character( $item, $post, $request ) {
		$item->data['title']['rendered'] = html_entity_decode( $item->data['title']['rendered'] );
		return $item;
	}

	public function taxonomy_decode_special_character( $item, $post, $request ) {
		$item->data['name'] = html_entity_decode( $item->data['name'] );
		$item->data['description'] = html_entity_decode( $item->data['description'] );
		return $item;
	}

	public function add_course_price( $response, $post, $request ) {
		$product_id = get_post_meta(
			$post->ID,
			'_academy_booking_product_id',
			true
		);
		if ( 'paid' === $response->data['meta']['_academy_booking_type'] ) {
			$product_id = get_post_meta(
				$post->ID,
				'_academy_booking_product_id',
				true
			);
			if ( ! $product_id ) {
				return $response;
			}
			$symbol = function_exists( 'get_woocommerce_currency_symbol' )
				? html_entity_decode(
					get_woocommerce_currency_symbol(),
					ENT_HTML5,
					'UTF-8'
				)
				: '';
			$prices = [];
			$regular_price = get_post_meta( $product_id, '_regular_price', true );
			$sale_price = get_post_meta( $product_id, '_sale_price', true );
			$response->data['academy_booking_regular_price'] = $regular_price;
			$response->data['academy_booking_sale_price'] = $sale_price;
			if ( $regular_price ) {
				$prices[] = $symbol . number_format( $regular_price, 2 );
			}
			if ( $sale_price ) {
				$prices[] = $symbol . number_format( $sale_price, 2 );
			}
			if ( count( $prices ) ) {
				$response->data['academy_booking_price'] = implode( ', ', $prices );
			}
		}//end if

		return $response;
	}

	public function check_academy_booking_schedule( $response, $handler, $request ) {
		$exist_post_id = (int) $request->get_param( 'id' );
		$meta = $request->get_param( 'meta' );

		// Validate meta parameters
		if ( empty( $meta['_academy_booking_schedule_time_zone'] ) ) {
			return $response;
		}

		$user_id = get_current_user_id();
		$have_booking = (int) count( get_posts( [
			'post_author' => $user_id,
			'post_status' => 'publish',
			'post_type'   => 'academy_booking',
		] ) );

		if ( 0 === $have_booking ) {
			return $response;
		}

		$post_author = (int) get_post_field( 'post_author', $exist_post_id );
		if ( $post_author !== $user_id && 0 !== $post_author ) {
			return $response;
		}

		$error_message = true;
		$type = isset( $meta['_academy_booking_schedule_type'] ) ? $meta['_academy_booking_schedule_type'] : '';
		$error_message = $this->is_booking_schedule_duplicate( $type, $meta, $user_id, $exist_post_id );
		if ( true !== $error_message ) {
			return new \WP_Error(
				'invalid_date_time',
				$error_message,
				[ 'status' => 400 ]
			);
		}

		return $response;
	}


	public function is_booking_schedule_duplicate( $type, $schedule_date, $user_id, $exist_post_id ) {
		global $wpdb;

		// Determine the meta key based on the schedule type
		$meta_key = ( 'single' === $type )
			? '_academy_booking_schedule_time'
			: '_academy_booking_schedule_repeated_times';

		$patterns = [];

		if ( 'single' === $type ) {
			$date = esc_sql( $schedule_date['_academy_booking_schedule_time']['date'] );
			$start_time = esc_sql( $schedule_date['_academy_booking_schedule_time']['start_time'] );
			$patterns[] = [
				'%"date";s:%:"' . $date . '";%',
				'%"start_time";s:%:"' . $start_time . '";%'
			];
		} elseif ( 'repeated' === $type ) {
			foreach ( $schedule_date['_academy_booking_schedule_repeated_times'] as $schedule ) {
				$day = esc_sql( $schedule['day'] );
				foreach ( $schedule['scheduleTimes'] as $time ) {
					$start_time = esc_sql( $time['start_time'] );
					$patterns[] = [
						'%"day";s:%:"' . $day . '";%',
						'%"start_time";s:%:"' . $start_time . '";%'
					];
				}
			}
		}

		foreach ( $patterns as $pattern ) {

			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$results = $wpdb->get_results( $wpdb->prepare(
				"SELECT pm.post_id 
				FROM {$wpdb->postmeta} pm
				INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID
				WHERE p.post_author = %d
				AND pm.meta_key = %s
				AND pm.meta_value LIKE %s
				AND pm.meta_value LIKE %s",
				$user_id, $meta_key, $pattern[0], $pattern[1]
			) );

			if ( ! empty( $exist_post_id ) && (int) count( $results ) === 1 ) {
				foreach ( $results as $post ) {
					if ( (int) $post->post_id === $exist_post_id ) {
						return true;
					}
				}
			}
			if ( ! empty( $results ) ) {
				$error_message = ( 'single' === $type )
					? sprintf(
						/* translators: %s is a date., %s is a time */
						esc_html__( 'The Date %1$s and Time %2$s Already Created.', 'academy-pro' ),
						$date,
						$start_time
					)
					: esc_html__( 'A Booking with the provided Day and Start Time Already Exists.', 'academy-pro' );

				return $error_message;
			}
		}//end foreach

		return true;
	}

}
