<?php

namespace AcademyProSurecart;

use SureCart\Integrations\Contracts\IntegrationInterface;
use SureCart\Integrations\Contracts\PurchaseSyncInterface;
use SureCart\Integrations\IntegrationService;
use SureCart\Models;
use SureCart\Models\Price;
use SureCart\Models\Product;
use SureCart\Support\Currency;
use AcademyProTutorBooking\Helper;

/**
 * Controls the LearnDash integration.
 */
class TutorIntegration extends IntegrationService implements IntegrationInterface, PurchaseSyncInterface {
	public function bootstrap() {
		parent::bootstrap();
		add_filter( 'academy_pro/single_booking/get_product_price', [ $this, 'get_product_price' ], 10, 2 );
		add_filter( 'academy_pro/template/booking/loop_price_args', [ $this, 'modify_loop_price_args' ], 10, 2 );
		add_filter( 'academy_pro/single_booking/price_args', [ $this, 'modify_booking_price_args' ], 10, 2 );
		add_filter( 'academy_pro/admin/get_booking_price', [ $this, 'get_booking_price' ], 10, 2 );
		add_action( 'surecart/models/price/updated', [ $this, 'clearPriceCache' ], 10, 2 );
		add_action( 'surecart/models/price/created', [ $this, 'clearPriceCache' ], 10, 2 );
	}

	public function modify_booking_price_args( $args, $booking_id ) {
		$booking_type = get_post_meta( $booking_id, '_academy_booking_type', true );
		if ( 'paid' === $booking_type ) {
			if ( \Academy\Helper::is_active_woocommerce() && 'woocommerce' === \Academy\Helper::get_settings( 'monetization_engine' ) ) {
				return $args;
			}
		}
		$prices = $this->check_integration_and_price( $args, $booking_id );
		if ( $prices === $args ) {
			return $args;
		}

		foreach ( $prices as $price ) {
			$args['is_paid'] = true;
			$args['price'] = '<span class="academy-surecart-price">' . Currency::format( $price->amount, $price->currency ) . '</span>';
			return $args;
		}
	}

	public function check_integration_and_price( $args, $course_id ) {
		$integrations = Models\Integration::where( 'integration_id', $course_id )->andWhere( 'model_name', 'product' )->get();
		if ( empty( $integrations ) ) {
			return $args;
		}
		$product_ids = array_column( $integrations, 'model_id' );

		foreach ( $integrations as $integration ) {
			$integration_id = $integration->getAttribute( 'integration_id' );
			if ( $integration_id && 'paid' !== get_post_meta( $integration_id, '_academy_booking_type', true ) ) {
				update_post_meta( $integration_id, '_academy_booking_type', 'paid' );
			}
		}
		if ( empty( $product_ids ) ) {
			return $args;
		}
		$prices = $this->getCachedProductsPrices( $product_ids );
		if ( empty( $prices ) ) {
			return $args;
		}

		return $prices;
	}

	public function get_product_price( $args, $booking_id ) {
		$prices = $this->check_integration_and_price( $args, $booking_id );
		if ( empty( $prices ) || $prices === $args ) {
			return $args;
		}
		$schedule_time = get_user_meta( $args['user_id'], 'booking_schdule_time_' . $booking_id, true );
		if ( $schedule_time !== $args['booked_schedule_date_time'] ) {
			add_user_meta( $args['user_id'], 'booking_schdule_time_' . $booking_id, $args['booked_schedule_date_time'] );
		}
		// add our components.
		\SureCart::assets()->enqueueComponents();
		foreach ( $prices as $price ) {
			return $price->id;
		}
	}

	public function get_booking_price( $args, $booking_id ) {
		$prices = $this->check_integration_and_price( $args, $booking_id );
		if ( $prices === $args ) {
			return $args;
		}

		foreach ( $prices as $price ) {
			return Currency::format( $price->amount, $price->currency );
		}
	}

	public function modify_loop_price_args( $args, $booking_id ) {
		$booking_type = get_post_meta( $booking_id, '_academy_booking_type', true );
		if ( 'paid' === $booking_type ) {
			if ( \Academy\Helper::is_active_woocommerce() && 'woocommerce' === \Academy\Helper::get_settings( 'monetization_engine' ) ) {
				return $args;
			}
		}

		$prices = $this->check_integration_and_price( $args, $booking_id );
		if ( empty( $prices ) || $prices === $args ) {
			return $args;
		}
		foreach ( $prices as $price ) {
			$args['price'] = Currency::format( $price->amount, $price->currency );
			$args['is_paid'] = true;
			return $args;
		}
	}

	public function getCachedProductsPrices( $product_ids = [] ) {
		$prices = [];
		foreach ( $product_ids as $product_id ) {
			$prices = array_merge( $prices, $this->getCachedProductPrices( $product_id ) );
		}
		return $prices;
	}

	public function getCachedProductPrices( $product_id ) {
		// cache key.
		$cache_key = 'academy_booking_surecart_product_' . $product_id;

		// get the transient.
		$prices = get_transient( $cache_key );

		// if we do not have a transient.
		if ( is_wp_error( $prices ) || ! $prices ) {
			// get purchasable prices for product.
			$prices = Price::where(
				[
					'product_ids' => [ $product_id ],
					'archived'    => false,
				]
			)->get();

			// store in transient.
			set_transient( $cache_key, $prices, apply_filters( 'academy_booking_surecart_product_cache_time', DAY_IN_SECONDS, $this ) );
		}

		return $prices;
	}

	/**
	 * Clear the price cache.
	 *
	 * @param \SureCart\Models\Price $price The price model.
	 *
	 * @return void
	 */
	public function clearPriceCache( $price ) {
		if ( empty( $price->product ) ) {
			return;
		}

		// get the product id.
		$product_id = is_a( $price->product, Product::class ) ? $price->product->id : $price->product;

		delete_transient( 'academy_booking_surecart_product_' . $product_id );
	}

	/**
	 * Get the slug for the integration.
	 *
	 * @return string
	 */
	public function getName() {
		return 'academy-pro/academy-booking';
	}

	/**
	 * Get the SureCart model used for the integration.
	 * Only 'product' is supported at this time.
	 *
	 * @return string
	 */
	public function getModel() {
		return 'product';
	}

	/**
	 * Get the integration logo url.
	 * This can be to a png, jpg, or svg for example.
	 *
	 * @return string
	 */
	public function getLogo() {
		return ACADEMY_ASSETS_URI . 'images/logo.svg';
	}

	/**
	 * The display name for the integration in the dropdown.
	 *
	 * @return string
	 */
	public function getLabel() {
		return __( 'Academy Tutor Booking', 'academy-pro' );
	}

	/**
	 * The label for the integration item that will be chosen.
	 *
	 * @return string
	 */
	public function getItemLabel() {
		return __( 'Tutor Booking Access', 'academy-pro' );
	}

	/**
	 * Help text for the integration item chooser.
	 *
	 * @return string
	 */
	public function getItemHelp() {
		return __( 'Enable access to a Academy Tutor Booking.', 'academy-pro' );
	}

	/**
	 * Is this enabled?
	 *
	 * @return boolean
	 */
	public function enabled() {
		return defined( 'ACADEMY_VERSION' );
	}

	/**
	 * Get item listing for the integration.
	 *
	 * @param array  $items The integration items.
	 * @param string $search The search term.
	 *
	 * @return array The items for the integration.
	 */
	public function getItems( $items = [], $search = '' ) {
		if ( ! class_exists( 'Academy' ) ) {
			return $items;
		}

		// phpcs:ignore WordPress.WP.DiscouragedFunctions.wp_reset_query_wp_reset_query
		wp_reset_query();
		$course_query = new \WP_Query(
			[
				'post_type'   => 'academy_booking',
				'post_status' => 'publish',
				's'           => $search,
				'per_page'    => 10,
			]
		);

		if ( ( isset( $course_query->posts ) ) && ( ! empty( $course_query->posts ) ) ) {
			$items = array_map(
				function( $post ) {
					return (object) [
						'id'    => $post->ID,
						'label' => $post->post_title,
					];
				},
				$course_query->posts
			);
		}

		return $items;
	}

	/**
	 * Get the individual item.
	 *
	 * @param string $id Id for the record.
	 *
	 * @return object The item for the integration.
	 */
	public function getItem( $id ) {
		$course = get_post( $id );
		if ( ! $course ) {
			return [];
		}

		// Return the course data
		return (object) array(
			'id'             => $id,
			'provider_label' => __( 'Academy Tutor Booking', 'academy-pro' ),
			'label'          => $course->post_title,
		);
	}


	/**
	 * Enable Access to the course.
	 *
	 * @param \SureCart\Models\Integration $integration The integrations.
	 * @param \WP_User                     $wp_user The user.
	 *
	 * @return boolean|void Returns true if the user course access updation was successful otherwise false.
	 */
	public function onPurchaseCreated( $integration, $wp_user ) {
		$this->updateAccess( $integration->integration_id, $wp_user, true );
	}

	/**
	 * Enable access when purchase is invoked
	 *
	 * @param \SureCart\Models\Integration $integration The integrations.
	 * @param \WP_User                     $wp_user The user.
	 *
	 * @return boolean|void Returns true if the user course access updation was successful otherwise false.
	 */
	public function onPurchaseInvoked( $integration, $wp_user ) {
		$this->onPurchaseCreated( $integration, $wp_user );
	}

	/**
	 * Remove a user role.
	 *
	 * @param \SureCart\Models\Integration $integration The integrations.
	 * @param \WP_User                     $wp_user The user.
	 *
	 * @return boolean|void Returns true if the user course access updation was successful otherwise false.
	 */
	public function onPurchaseRevoked( $integration, $wp_user ) {
		$this->updateAccess( $integration->integration_id, $wp_user, false );
	}

	/**
	 * Update access to a course.
	 *
	 * @param integer  $booking_id The booking id.
	 * @param \WP_User $wp_user The user.
	 * @param boolean  $add True to add the user to the course, false to remove.
	 *
	 * @return boolean|void Returns true if the user course access updation was successful otherwise false.
	 */
	public function updateAccess( $booking_id, $wp_user, $add = true ) {

		$schedule_date_time = get_user_meta( $wp_user->ID, 'booking_schdule_time_' . $booking_id, true );
		$is_booked = Helper::do_booked( $booking_id, $wp_user->ID, $schedule_date_time );
		if ( $is_booked ) {
			delete_user_meta( $wp_user->ID, 'booking_schdule_time_' . $booking_id, $schedule_date_time );
		}

	}
}

