<?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;

/**
 * Controls the LearnDash integration.
 */
class Integration extends IntegrationService implements IntegrationInterface, PurchaseSyncInterface {
	public function bootstrap() {
		parent::bootstrap();
		add_filter( 'academy/templates/single_course/enroll_form', [ $this, 'add_to_cart_button' ], 10, 2 );
		add_filter( 'academy/single/enroll_content_args', [ $this, 'modify_enroll_form_content_args' ], 10, 2 );
		add_filter( 'academy/template/loop/price_args', [ $this, 'modify_loop_price_args' ], 10, 2 );
		add_filter( 'rest_prepare_academy_courses', [ $this, 'add_course_price' ], 11, 2 );
		add_filter( 'academy/surecart/get_course_prices', [ $this, 'get_course_prices' ] );

		add_action( 'surecart/models/price/updated', [ $this, 'clearPriceCache' ], 10, 2 );
		add_action( 'surecart/models/price/created', [ $this, 'clearPriceCache' ], 10, 2 );
	}
	public function modify_enroll_form_content_args( $args, $course_id ) {
		if ( $args['is_public'] ) {
			return $args;
		}

		$prices = $this->check_integration_and_price( $args, $course_id );
		if ( $prices === $args ) {
			return $args;
		}

		$prices_markup = $this->get_price_html( $prices );
		$args['is_paid'] = true;
		$args['price'] = '<div class="academy-course-type">' . $prices_markup . '</div>';

		return $args;
	}
	public function modify_loop_price_args( $args, $course_id ) {
		if ( 'public' === $args['course_type'] ) {
			return $args;
		}
		$prices = $this->check_integration_and_price( $args, $course_id );
		if ( $prices === $args ) {
			return $args;
		}

		$prices_markup = $this->get_price_html( $prices );
		$args['is_paid'] = true;
		$args['course_type'] = 'paid';
		$args['price'] = '<div class="academy-course-type">' . $prices_markup . '</div>';

		return $args;
	}

	public function add_course_price( $response, $post ) {
		if ( 'public' === $response->data['meta']['academy_course_type'] ) {
			return $response;
		}

		$prices = $this->check_integration_and_price( $response, $post->ID );
		if ( $prices === $response ) {
			return $response;
		}

		foreach ( $prices as $price ) {
			$value[] = Currency::format( $price->amount, $price->currency );
		}
		$response->data['meta']['academy_course_type'] = 'paid';
		$response->data['academy_course_price'] = implode( '|', $value );
		$response->data['meta']['academy_ecommerce_engine'] = 'surecart';

		return $response;
	}

	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_course_type', true ) ) {
				update_post_meta( $integration_id, 'academy_course_type', 'paid' );
			}
		}
		if ( empty( $product_ids ) ) {
			return $args;
		}
		$prices = $this->getCachedProductsPrices( $product_ids );
		if ( empty( $prices ) ) {
			return $args;
		}

		return $prices;
	}

	public function get_price_html( $prices ) {
		$prices_markup = '';
		$number_of_price = count( $prices );
		foreach ( $prices as $price ) {
			if ( $number_of_price > 1 ) {
				$prices_markup .= '<span class="academy-surecart-price">' . __( 'Paid', 'academy-pro' ) . '</span>';
				break;
			}
			$prices_markup .= '<span class="academy-surecart-price">' . Currency::format( $price->amount, $price->currency ) . '</span>';
		}
		return $prices_markup;
	}

	public function add_to_cart_button( $html, $course_id ) {
		$prices = $this->check_integration_and_price( $html, $course_id );
		$user_id = get_current_user_id();
		if ( empty( $prices ) || \Academy\Helper::is_enrolled( $course_id, $user_id ) || $prices === $html ) {
			return $html;
		}

		// add our components.
		\SureCart::assets()->enqueueComponents();

		ob_start();
		\AcademyPro\Helper::get_template('surecart/add-to-cart.php', array(
			'prices' => $prices,
		) );

		return ob_get_clean();
	}

	public function get_course_prices( $course_id ) {
		$html = '';
		$prices = $this->check_integration_and_price( $html, $course_id );
		if ( empty( $prices ) ) {
			return $html;
		}

		// add our components.
		\SureCart::assets()->enqueueComponents();
		return $prices;
	}

	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_lms_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_lms_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_lms_surecart_product_' . $product_id );
	}

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

	/**
	 * 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 LMS', 'academy-pro' );
	}

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

	/**
	 * Help text for the integration item chooser.
	 *
	 * @return string
	 */
	public function getItemHelp() {
		return __( 'Enable access to a Academy LMS course.', '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_courses',
				'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 LMS Course', '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  $course_id The course 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( $course_id, $wp_user, $add = true ) {
		if ( ! $add ) {
			\Academy\Helper::cancel_course_enroll( $course_id, $wp_user->ID );
			return;
		}
		\Academy\Helper::do_enroll( $course_id, $wp_user->ID );
	}
}

