<?php
/**
 * Masteriyo Coupons Addon Setup.
 *
 * @package Masteriyo\Addons\Coupons
 *
 * @since 2.5.12
 */

namespace Masteriyo\Addons\Coupons;

use Masteriyo\Constants;
use Masteriyo\Addons\Coupons\PostType\Coupon;
use Masteriyo\Addons\Coupons\Controllers\CouponsController;
use Masteriyo\Addons\Coupons\Enums\CouponStatus;
use Masteriyo\Addons\Coupons\Enums\DeductionMethodType;
use Masteriyo\Addons\Coupons\Listener\NewCouponsListener;
use Masteriyo\Traits\Singleton;

defined( 'ABSPATH' ) || exit;

/**
 * Main Masteriyo Coupons class.
 *
 * @class Masteriyo\Addons\Coupons\CouponsAddon
 */

class CouponsAddon {
	use Singleton;


	/**
	 * Coupons class instance.
	 *
	 * @since 2.5.23
	 *
	 * @var \Masteriyo\Addons\Coupons\Coupons
	 */
	protected $coupons;

	/**
	 * Initialize the application.
	 *
	 * @since 2.5.12
	 */
	public function init() {
		$this->init_hooks();
	}

	/**
	 * Initialize hooks.
	 *
	 * @since 2.5.12
	 */
	public function init_hooks() {
		add_filter( 'masteriyo_admin_submenus', array( $this, 'register_coupons_submenu' ) );
		add_filter( 'masteriyo_register_post_types', array( $this, 'register_coupon_post_type' ) );
		add_filter( 'masteriyo_rest_api_get_rest_namespaces', array( $this, 'register_coupons_namespace' ) );
		add_filter( 'masteriyo_ajax_handlers', array( $this, 'register_ajax_handlers' ) );
		add_action( 'masteriyo_checkout_summary_your_order_before_total_row', array( $this, 'template_applied_coupons' ), 10 );
		add_action( 'masteriyo_checkout_summary_your_order_before_total_row', array( $this, 'template_checkout_apply_coupon' ), 10 );
		add_action( 'masteriyo_thankyou_page_before_total_row', array( $this, 'template_thankyou_page_before_total_row' ), 10 );
		add_filter( 'masteriyo_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10 );
		add_filter( 'masteriyo_rest_response_order_data', array( $this, 'modify_rest_response_order_data' ), 10, 4 );
		add_action( 'masteriyo_before_init', array( $this, 'handle_masteriyo_before_init' ) );
		add_filter( 'masteriyo_rest_response_subscription_data', array( $this, 'modify_rest_response_subscription_data' ), 10, 3 );
		add_filter( 'masteriyo_webhook_listeners', array( $this, 'register_listener_class' ) );
	}

	/**
	 * Register coupon status.
	 *
	 * @since 2.5.26
	 */
	private function register_coupon_status() {
		foreach ( CouponStatus::list() as $coupon_status => $values ) {
			register_post_status( $coupon_status, $values );
		}
	}

	/**
	 * Callback for the `masteriyo_before_init` hook.
	 *
	 * @since 2.5.23
	 */
	public function handle_masteriyo_before_init() {
		$this->coupons = masteriyo( 'coupons' );
		$this->coupons->init();

		$this->register_coupon_status();
	}

	/**
	 * Register Listeners.
	 *
	 * @since 2.8.3
	 *
	 * @param array $listeners
	 * @return array
	 */
	public function register_listener_class( $listeners ) {
		$listeners[] = NewCouponsListener::class;

		return $listeners;
	}

	/**
	 * Register coupon submenu.
	 *
	 * @since 2.5.12
	 *
	 * @param array $submenus Admin submenus.
	 * @return array
	 */
	public function register_coupons_submenu( $submenus ) {
		$submenus['coupons'] = array(
			'page_title' => __( 'Coupons', 'learning-management-system' ),
			'menu_title' => __( 'Coupons', 'learning-management-system' ),
			'position'   => 69,
		);

		return $submenus;
	}

	/**
	 * Register coupon post types.
	 *
	 * @since 2.5.12
	 *
	 * @param string[] $post_types
	 * @return string[]
	 */
	public function register_coupon_post_type( $post_types ) {
		$post_types[] = Coupon::class;

		return $post_types;
	}

	/**
	 * Register coupons controller.
	 *
	 * @since 2.5.12
	 *
	 * @param array $controllers
	 * @return array
	 */
	public function register_coupons_namespace( $controllers ) {
		$controllers['masteriyo/pro/v1']['coupons'] = CouponsController::class;

		return $controllers;
	}

	/**
	 * Register AJAX handlers.
	 *
	 * @since 2.5.12
	 *
	 * @param string[] $handlers
	 *
	 * @return string[]
	 */
	public function register_ajax_handlers( $handlers ) {
		$handlers[] = ApplyCouponAjaxHandler::class;
		$handlers[] = RemoveAppliedCouponAjaxHandler::class;

		return $handlers;
	}

	/**
	 * Render template for apply-coupon form.
	 *
	 * @since 2.5.12
	 */
	public function template_checkout_apply_coupon() {
		$cart = masteriyo_create_cart_object();
		include __DIR__ . '/templates/checkout/apply-coupon.php';
	}

	/**
	 * Render template for listing applied coupons.
	 *
	 * @since 2.5.12
	 */
	public function template_applied_coupons() {
		$cart             = masteriyo_create_cart_object();
		$coupon_discounts = masteriyo( 'coupons' )->get_discount_totals_by_coupon();

		$cart_contents = $cart->get_cart_contents();
		$currency      = '';

		if ( ! empty( $cart_contents ) ) {
			foreach ( $cart_contents  as $cart_item ) {

				$course = $cart_item['data'];

				if ( ! $course instanceof \Masteriyo\Models\Course ) {
					return $cart_item;
				}

				$currency = $course->get_currency();
				break;
			}
		}

		include __DIR__ . '/templates/checkout/applied-coupons.php';
	}

	/**
	 * Render template for discounts row in thankyou page.
	 *
	 * @since 2.5.12
	 *
	 * @param \Masteriyo\Models\Order\Order $order
	 */
	public function template_thankyou_page_before_total_row( $order ) {
		include __DIR__ . '/templates/thankyou/discounts.php';
	}

	/**
	 * Enqueue scripts.
	 *
	 * @since 2.5.12
	 *
	 * @param array $scripts
	 */
	public function enqueue_scripts( $scripts ) {
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';

		$scripts['coupons'] = array(
			'src'      => plugin_dir_url( Constants::get( 'MASTERIYO_COUPONS_ADDON_FILE' ) ) . '/js/coupons' . $suffix . '.js',
			'deps'     => array( 'jquery', 'masteriyo-jquery-block-ui' ),
			'context'  => 'public',
			'callback' => 'masteriyo_is_checkout_page',
		);
		return $scripts;
	}

	/**
	 * Filter Order rest response data.
	 *
	 * @since 2.5.12
	 *
	 * @param array $data Order data.
	 * @param \Masteriyo\Models\Order\Order $order Order object.
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @param \Masteriyo\RestApi\Controllers\Version1\OrdersController $controller REST Orders controller object.
	 *
	 * @return array
	 */
	public function modify_rest_response_order_data( $data, $order, $context, $controller ) {
		$data['discount_total'] = $order->get_discount_total( $context );
		$data['coupon_lines']   = $this->get_order_item_coupons( $order->get_items( 'coupon' ), $context );
		return $data;
	}

	/**
	 * Get course order items.
	 *
	 * @since 2.5.12
	 *
	 * @param \Masteriyo\Models\Order\OrderItem[] $items
	 *
	 * @return array
	 */
	protected function get_order_item_coupons( $items, $context ) {
		$course_items = array_filter(
			$items,
			function( $item ) {
				return 'coupon' === $item->get_type();
			}
		);

		$data = array();

		foreach ( $course_items as $course_item ) {
			$code   = $course_item->get_name( $context );
			$coupon = masteriyo_get_coupon_by_code( $code );

			if ( $coupon && DeductionMethodType::AUTOMATIC === $coupon->get_method( $context ) ) {
				$code = $coupon->get_description( $context );
			}

			$data[] = array(
				'id'       => $course_item->get_id(),
				'code'     => $code,
				'discount' => $course_item->get_discount( $context ),
			);
		}

		return $data;
	}

	/**
	 * Modify subscription rest response data.
	 *
	 * @since 2.6.10
	 * @param array $data Subscription rest data.
	 * @param \Masteriyo\Pro\Models\Subscription $subscription Subscription object.
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @return array
	 */
	public function modify_rest_response_subscription_data( $data, $subscription, $context ) {
		$order = masteriyo_get_order( $subscription->get_parent_id() );

		if ( $order ) {
			$data['discount_total'] = $order->get_discount_total( $context );
			$data['coupon_lines']   = $this->get_order_item_coupons( $order->get_items( 'coupon' ), $context );
		}

		return $data;
	}
}
