<?php
/**
 * Multiple Currency Addon for Masteriyo.
 *
 * @since 1.11.0 [free]
 */

namespace Masteriyo\Addons\MultipleCurrency;

use Masteriyo\Addons\Coupons\Enums\CouponDiscountType;
use Masteriyo\Addons\Coupons\Models\Coupon;
use Masteriyo\Addons\MultipleCurrency\AjaxHandlers\SwitchCurrencyAjaxHandler;
use Masteriyo\Addons\MultipleCurrency\Controllers\MultipleCurrencySettingsController;
use Masteriyo\Addons\MultipleCurrency\Controllers\PriceZonesController;
use Masteriyo\Addons\MultipleCurrency\MaxMind\DatabaseService;
use Masteriyo\Addons\MultipleCurrency\PostType\PriceZone;
use Masteriyo\Constants;
use Masteriyo\Traits\Singleton;

/**
 * Multiple Currency Addon main class for Masteriyo.
 *
 * @since 1.11.0 [free]
 */
class MultipleCurrencyAddon {
	use Singleton;

	/**
	 * Initialize.
	 *
	 * @since 1.11.0 [free]
	 */
	public function init() {
		$this->init_hooks();
	}

	/**
	 * Initializes the hooks for the Multiple Currency addon.
	 *
	 * This method sets up various filters and actions to handle multiple currency functionality,
	 * such as adding schema to the course REST API, saving multiple currency data, modifying
	 * currency and prices based on the user's country, registering a multiple currency submenu,
	 * registering a price zone post type, and registering REST API namespaces.
	 *
	 * @since 1.11.0 [free]
	 */
	public function init_hooks() {
		add_filter( 'masteriyo_admin_submenus', array( $this, 'register_multiple_currency_submenu' ) );
		add_filter( 'masteriyo_register_post_types', array( $this, 'register_price_zone_post_type' ) );
		add_filter( 'masteriyo_rest_api_get_rest_namespaces', array( $this, 'register_rest_namespaces' ) );

		add_filter( 'masteriyo_rest_course_schema', array( $this, 'add_multiple_currency_schema_to_course' ) );
		add_action( 'masteriyo_new_course', array( $this, 'save_multiple_currency_data' ), 10, 2 );
		add_action( 'masteriyo_update_course', array( $this, 'save_multiple_currency_data' ), 10, 2 );
		add_filter( 'masteriyo_rest_response_course_data', array( $this, 'append_multiple_currency_data_in_response' ), 10, 4 );
		add_filter( 'masteriyo_rest_response_course_bundle_data', array( $this, 'append_multiple_currency_data_in_response' ), 10, 4 );
		add_action( 'masteriyo_new_course_bundle', array( $this, 'save_multiple_currency_data' ), 10, 2 );
		add_action( 'masteriyo_update_course_bundle', array( $this, 'save_multiple_currency_data' ), 10, 2 );
		add_filter( 'masteriyo_setup_course_data', array( $this, 'modify_price_on_frontend_page' ) ); // For single course page.
		add_filter( 'masteriyo_course_archive_course', array( $this, 'modify_price_on_frontend_page' ) ); // For course archive page.
		add_filter( 'masteriyo_checkout_modify_course_details', array( $this, 'modify_price_on_frontend_page' ) ); // For order summary page.
		add_filter( 'masteriyo_checkout_modify_course_details', array( $this, 'modify_price_on_frontend_page_for_course_bundle' ) ); // For order summary page.
		add_filter( 'masteriyo_course_archive_bundle', array( $this, 'modify_price_on_frontend_page_for_course_bundle' ) ); // For course bundle archive page.
		add_filter( 'masteriyo_single_course_bundle', array( $this, 'modify_price_on_frontend_page_for_course_bundle' ) ); // For single course bundle page.
		add_filter( 'masteriyo_courses_of_course_bundle', array( $this, 'modify_price_on_frontend_page_for_course_bundle' ), 10, 2 ); // For single course within a specific course bundle page.
		add_filter( 'masteriyo_group_buy_btn_price', array( $this, 'modify_group_course_price' ), 10, 2 ); // For modification of course price for the group in single course page.

		add_filter( 'masteriyo_cart_contents_changed', array( $this, 'add_multiple_currency_course_content_to_cart_contents' ), 11, 1 );

		add_filter( 'masteriyo_rest_prepare_countries_list', array( $this, 'modify_countries_list' ), 10, 2 );

		add_filter( 'masteriyo_get_geolocation', array( $this, 'get_geolocation' ), 10, 2 );

		add_action( 'masteriyo_new_earning', array( $this, 'update_earning' ), 10, 2 );

		add_filter( 'masteriyo_coupon_get_apply_discount_amount', array( $this, 'modify_discount_amount' ), 10, 4 );

		add_action( 'masteriyo_before_destroy_cart_session', array( $this, 'before_destroy_cart_session' ), 10, 1 );

		add_filter( 'masteriyo_get_template', array( $this, 'change_template_for_multiple_currency' ), 10, 5 );
		add_action( 'masteriyo_checkout_summary_order_details', array( $this, 'template_checkout_switch_currency' ), 5 );

		add_filter( 'masteriyo_ajax_handlers', array( $this, 'register_ajax_handlers' ) );
		add_filter( 'masteriyo_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10 );
	}

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

		$scripts['multiple-currency'] = array(
			'src'      => Constants::get( 'MASTERIYO_MULTIPLE_CURRENCY_ADDON_ASSETS_URL' ) . '/js/frontend/multiple-currency' . $suffix . '.js',
			'deps'     => array( 'jquery', 'masteriyo-jquery-block-ui' ),
			'context'  => 'public',
			'callback' => 'masteriyo_is_checkout_page',
		);

		return $scripts;
	}

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

		return $handlers;
	}

	/**
	 * Renders the template for switching the currency on the checkout page.
	 *
	 * @since 2.11.0
	 *
	 * @param \Masteriyo\Models\Course $course The course object.
	 */
	public function template_checkout_switch_currency( $course ) {
		if ( is_a( $course, 'Masteriyo\Models\Course' ) || is_a( $course, 'Masteriyo\Addons\CourseBundle\Models\CourseBundle' ) ) {
			$currencies = masteriyo_get_active_currencies_by_course_and_bundle( $course );

			masteriyo_get_template(
				'multiple-currency/switch-currency.php',
				array(
					'currencies' => $currencies,
					'course'     => $course,
				)
			);
		}
	}

	/**
	 * Changes the template path for specific group courses related templates.
	 *
	 * @since 2.11.0
	 *
	 * @param string $template Template path.
	 * @param string $template_name Template name.
	 * @param array $args Template arguments.
	 * @param string $template_path Template path from function parameter.
	 * @param string $default_path Default templates directory path.
	 *
	 * @return string
	 */
	public function change_template_for_multiple_currency( $template, $template_name, $args, $template_path, $default_path ) {
		$template_map = array(
			'multiple-currency/switch-currency.php' => 'switch-currency.php',
		);

		if ( isset( $template_map[ $template_name ] ) ) {
			$new_template = trailingslashit( Constants::get( 'MASTERIYO_MULTIPLE_CURRENCY_TEMPLATES' ) ) . $template_map[ $template_name ];

			return file_exists( $new_template ) ? $new_template : $template;
		}

		return $template;
	}

	/**
	 * Removes the selected currency from the session when the cart is destroyed.
	 *
	 * @since 2.11.0
	 *
	 * @param \Masteriyo\Cart\Cart $cart
	 */
	public function before_destroy_cart_session( $cart ) {
		masteriyo_create_session_object()->put( 'selected_currency', null );
	}

	/**
	 * Modifies the discount amount for an item.
	 *
	 * @since 2.11.0
	 *
	 * @param float $amount The amount to apply the coupon to.
	 * @param objet $item The item data.
	 * @param \Masteriyo\Addons\Coupons\Models\Coupon  $coupon The coupon object.
	 * @param \Masteriyo\Addons\Coupons\CouponDiscounts $discounts The CouponDiscounts instance.
	 */
	public function modify_discount_amount( $discount, $item, $coupon, $discounts ) {

		if ( ! $coupon instanceof Coupon ) {
			return $discount;
		}

		if ( CouponDiscountType::FIXED_CART !== $coupon->get_discount_type() ) {
			return $discount;
		}

		if ( ! isset( $item->object, $item->object['data'] ) ) {
			return $discount;
		}

		$course = $item->object['data'];

		if ( ! $course instanceof \Masteriyo\Models\Course || ! $coupon instanceof \Masteriyo\Addons\Coupons\Models\Coupon ) {
			return $discount;
		}

		if ( ! $course->get_currency() || ! $course->get_exchange_rate() ) {
			return $discount;
		}

		$selected_currency = masteriyo_create_session_object()->get( 'selected_currency', '' );

		if ( masteriyo_get_currency() === $selected_currency ) {
			return $discount;
		}

		$discount = masteriyo_remove_number_precision( $discount );

		$discount *= floatval( $course->get_exchange_rate() );

		if ( $discount > floatval( $course->get_price() ) ) {
			$discount = floatval( $course->get_price() );
		}

		$discount = masteriyo_add_number_precision( $discount );

		return $discount;
	}

	/**
	 * Updates the earning after creation, converting amounts from local currency to base currency if necessary.
	 *
	 * This function is fired after creating an earning and checks if the earning is in local currency.
	 * If the earning is in local currency, it converts the amounts to the base currency using the provided exchange rate.
	 *
	 * @since 1.11.0 [free]
	 *
	 * @param \Masteriyo\Addons\RevenueSharing\Models\Earning $earning The earning object.
	 * @param integer $id The earning ID.
	 */
	public function update_earning( $earning, $id ) {
		if ( ! $earning instanceof \Masteriyo\Addons\RevenueSharing\Models\Earning ) {
			return;
		}

		$order = masteriyo_get_order( $earning->get_order_id() );

		if ( ! $order ) {
			return;
		}

		$exchange_rate = $order->get_exchange_rate();

		if ( masteriyo_get_currency() === $order->get_currency() ) {
			return;
		}

		if ( $order->get_base_currency() && $exchange_rate ) {
			$conversion_factor = 1 / $exchange_rate;

			$earning->set_grand_total_amount( masteriyo_format_decimal( $earning->get_grand_total_amount() * $conversion_factor ) );
			$earning->set_total_amount( masteriyo_format_decimal( $earning->get_total_amount() * $conversion_factor ) );
			$earning->set_admin_amount( masteriyo_format_decimal( $earning->get_admin_amount() * $conversion_factor ) );
			$earning->set_instructor_amount( masteriyo_format_decimal( $earning->get_instructor_amount() * $conversion_factor ) );
			$earning->set_deductible_fee_amount( $earning->get_deductible_fee_amount() * $conversion_factor );

			$earning->save();
		}
	}

	/**
	 * Performs a geolocation lookup against the MaxMind database for the given IP address.
	 *
	 * @since 1.11.0 [free]
	 *
	 * @param array  $data       Geolocation data.
	 * @param string $ip_address The IP address to geolocate.
	 *
	 * @return array Geolocation including country code, state, city and postcode based on an IP address.
	 */
	public function get_geolocation( $data, $ip_address ) {
		if ( ! empty( $data['country'] ) ) {
			return $data;
		}

		if ( empty( $ip_address ) ) {
			return $data;
		}

		$database_service = new DatabaseService();

		$country_code = $database_service->get_iso_country_code_for_ip( $ip_address );

		return array(
			'country'  => $country_code,
			'state'    => '',
			'city'     => '',
			'postcode' => '',
		);
	}

	/**
	 * Modifies the list of countries based on the multiple currency settings.
	 *
	 * If the request is from the multiple currency context, this function will return the list of countries that are not yet assigned to any pricing zone.
	 *
	 * @since 1.11.0 [free]
	 *
	 * @param array           $countries      The list of countries.
	 * @param \WP_REST_Request $request The current REST request.
	 *
	 * @return array The modified list of countries.
	 */
	public function modify_countries_list( $countries, $request ) {
		$is_from_multiple_currency = masteriyo_string_to_bool( $request->get_param( 'is_from_multiple_currency' ) ?? false );
		$price_zone_id             = absint( $request->get_param( 'price_zone_id' ) ?? 0 );

		if ( $is_from_multiple_currency ) {
			$countries = masteriyo_get_unused_country_list_for_pricing_zone( $price_zone_id );

			$countries = array_map(
				function ( $code ) {
					return array( $code => masteriyo( 'countries' )->get_country_from_code( $code ) );
				},
				$countries
			);

			$countries = call_user_func_array( 'array_merge_recursive', $countries );
		}

		return $countries;
	}

	/**
	 * Adjusts the price of multiple currency courses in the cart.
	 *
	 * @since 1.11.0 [free]
	 *
	 * @param array $cart_contents The current contents of the cart.
	 *
	 * @return array Modified cart contents with updated pricing for multiple currency courses.
	 */
	public function add_multiple_currency_course_content_to_cart_contents( $cart_contents ) {
		if ( ! is_array( $cart_contents ) || empty( $cart_contents ) ) {
			return $cart_contents;
		}

		$cart_contents = array_map(
			function ( $cart_item ) {

				$course = $cart_item['data'];

				if ( ( ! $course instanceof \Masteriyo\Models\Course && 'mto-course-bundle' !== $course->get_post_type() ) || ( ! $course instanceof \Masteriyo\Addons\CourseBundle\Models\CourseBundle && 'mto-course' !== $course->get_post_type() ) ) {
					return $cart_item;
				}

				if ( ! masteriyo_string_to_bool( get_post_meta( $course->get_id(), '_multiple_currency_enabled', true ) ) ) {
					return $cart_item;
				}

				$selected_currency = masteriyo_create_session_object()->get( 'selected_currency', '' );

				if ( $selected_currency ) {
					if ( masteriyo_get_currency() === $selected_currency ) {
						return $cart_item;
					}

					$pricing_zone = masteriyo_get_price_zone_by_currency( $selected_currency );
				} else {
					$pricing_zone = masteriyo_get_price_zone_by_country( masteriyo_get_user_current_country() );
				}

				if ( ! $pricing_zone || ! masteriyo_string_to_bool( get_post_meta( $course->get_id(), "_multiple_currency__{$pricing_zone->get_id()}_enabled", true ) ) ) {

					return $cart_item;
				}

				$currency = $pricing_zone->get_currency();

				if ( empty( $currency ) || masteriyo_get_currency() === $currency ) {
					return $cart_item;
				}

				$regular_price = null;
				$sale_price    = null;

				if ( ( $course instanceof \Masteriyo\Models\Course && 'mto-course-bundle' === $course->get_post_type() ) ) {
					$regular_price = masteriyo_get_country_based_price_for_for_course_bundle( $course, $pricing_zone );
					$sale_price    = masteriyo_get_country_based_sale_price( $course, $pricing_zone );
				} else {
					// Check if the cart item is a group course.
					if ( isset( $cart_item['group_ids'] ) && isset( $cart_item['group_price'] ) ) {
						$group_price = $cart_item['group_price'];
						if ( ! empty( $cart_item['group_ids'] ) && ! empty( $group_price ) ) {

							$modified_group_price = masteriyo_get_country_based_group_course_price( $course->get_id(), $group_price, $pricing_zone );

							if ( $modified_group_price ) {
								$regular_price = $modified_group_price;
							}

							$sale_price = null;
						}
					} else {
						$regular_price = masteriyo_get_country_based_price( $course, $pricing_zone );
						$sale_price    = masteriyo_get_country_based_sale_price( $course, $pricing_zone );
					}
				}

				if ( ! is_null( $regular_price ) ) {
					$course->set_regular_price( $regular_price );
				}

				if ( ! is_null( $sale_price ) ) {
					$course->set_sale_price( $sale_price );
					$course->set_price( $sale_price );
				} else {
					$course->set_price( $regular_price );
					$course->set_sale_price( '' );
				}

				if ( ! is_null( $regular_price ) ) {
					if ( ! empty( $currency ) && ! is_null( $currency ) ) {
						$course->set_currency( $currency );
						$course->set_exchange_rate( $pricing_zone->get_exchange_rate() );
						$course->set_pricing_method( get_post_meta( $course->get_id(), "_multiple_currency_{$pricing_zone->get_id()}_pricing_method", true ) );
					}
				}

				$cart_item['data'] = $course;

				return $cart_item;
			},
			$cart_contents
		);

		return $cart_contents;
	}

	/**
	 * Modifies the price and sale price of a course based on the user's current country.
	 *
	 * This function checks if the course object is valid, then retrieves the country-based regular price and sale price for the course. It sets the course's price and regular price to the country-based regular price, and sets the course's sale price to the country-based sale price.
	 *
	 * @since 1.11.0 [free]
	 *
	 * @param \Masteriyo\Models\Course $course The course object.
	 *
	 * @return \Masteriyo\Models\Course The modified course object with updated prices.
	 */
	public function modify_price_on_frontend_page( $course, $is_courses_bundle = false ) {
		if ( ! $course instanceof \Masteriyo\Models\Course ) {
			return $course;
		}

		if ( ! masteriyo_string_to_bool( get_post_meta( $course->get_id(), '_multiple_currency_enabled', true ) ) ) {
			return $course;
		}

		if ( masteriyo_is_single_course_page() || masteriyo_is_courses_page( true ) || masteriyo_is_checkout_page() || is_callable( 'masteriyo_is_archive_course_bundle_page' ) && masteriyo_is_single_course_bundle_page() || is_callable( 'masteriyo_is_archive_course_bundle_page' ) && masteriyo_is_archive_course_bundle_page( true ) ) {

			$selected_currency = masteriyo_create_session_object()->get( 'selected_currency', '' );

			if ( $selected_currency ) {
				if ( masteriyo_get_currency() === $selected_currency ) {
					return $course;
				}

				$pricing_zone = masteriyo_get_price_zone_by_currency( $selected_currency );
			} else {
				$pricing_zone = masteriyo_get_price_zone_by_country( masteriyo_get_user_current_country() );
			}

			if ( ! $pricing_zone || ! masteriyo_string_to_bool( get_post_meta( $course->get_id(), "_multiple_currency__{$pricing_zone->get_id()}_enabled", true ) ) ) {
				return $course;
			}

			$currency = $pricing_zone->get_currency();

			if ( empty( $currency ) || masteriyo_get_currency() === $currency ) {
				return $course;
			}

			// if ( $is_courses_bundle ) {
			//  $regular_price = masteriyo_get_country_based_price( $course, $pricing_zone, true );
			//  $sale_price    = masteriyo_get_country_based_sale_price( $course, $pricing_zone, true );
			//  if ( ! is_null( $sale_price ) ) {
			//      return $sale_price;
			//  } else {
			//      return $regular_price;
			//  }
			// }
			$regular_price = masteriyo_get_country_based_price( $course, $pricing_zone );
			$sale_price    = masteriyo_get_country_based_sale_price( $course, $pricing_zone );
			if ( ! is_null( $regular_price ) ) {
				$course->set_regular_price( $regular_price );
			}

			if ( ! is_null( $sale_price ) ) {
				$course->set_sale_price( $sale_price );
				$course->set_price( $sale_price );
			} else {
				$course->set_price( $regular_price );
				$course->set_sale_price( '' );
			}

			if ( ! is_null( $regular_price ) || ! is_null( $sale_price ) ) {
				if ( ! empty( $currency ) && ! is_null( $currency ) ) {
					$course->set_currency( $currency );
				}
			}
		}

		return $course;
	}

	/**
	 * Modifies the price and sale price of a course bundle based on the user's current country.
	 *
	 * This function checks if the course object is valid, then retrieves the country-based regular price and sale price for the course. It sets the course's price and regular price to the country-based regular price, and sets the course's sale price to the country-based sale price.
	 *
	 * @since 2.14.0
	 *
	 * @param \Masteriyo\Models\CourseBundle $course The course bundle object.
	 *
	 * @return \Masteriyo\Models\CourseBundle The modified course bundle object with updated prices.
	 */
	public function modify_price_on_frontend_page_for_course_bundle( $course_bundle, $total_price_for_course = false ) {

		if ( ! $course_bundle instanceof \Masteriyo\Addons\CourseBundle\Models\CourseBundle ) {
			return $course_bundle;
		}

		if ( ! masteriyo_string_to_bool( get_post_meta( $course_bundle->get_id(), '_multiple_currency_enabled', true ) ) ) {
			return $course_bundle;
		}

		if ( masteriyo_is_single_course_bundle_page() || masteriyo_is_archive_course_bundle_page( true ) || masteriyo_is_checkout_page() ) {

			$selected_currency = masteriyo_create_session_object()->get( 'selected_currency', '' );

			if ( $selected_currency ) {
				if ( masteriyo_get_currency() === $selected_currency ) {
					return $course_bundle;
				}

				$pricing_zone = masteriyo_get_price_zone_by_currency( $selected_currency );
			} else {
				$pricing_zone = masteriyo_get_price_zone_by_country( masteriyo_get_user_current_country() );
			}

			if ( ! $pricing_zone || ! masteriyo_string_to_bool( get_post_meta( $course_bundle->get_id(), "_multiple_currency__{$pricing_zone->get_id()}_enabled", true ) ) ) {

				return $course_bundle;
			}

			$currency = $pricing_zone->get_currency();

			if ( $total_price_for_course ) {
				return masteriyo_get_country_based_price_for_for_course_bundle( $course_bundle, $pricing_zone, $total_price_for_course );
			}
			if ( empty( $currency ) || masteriyo_get_currency() === $currency ) {
				return $course_bundle;
			}

			$regular_price = masteriyo_get_country_based_price_for_for_course_bundle( $course_bundle, $pricing_zone );
			$sale_price    = masteriyo_get_country_based_sale_price( $course_bundle, $pricing_zone );
			if ( ! is_null( $regular_price ) ) {
				$course_bundle->set_regular_price( $regular_price );
			}

			if ( ! is_null( $sale_price ) ) {
				$course_bundle->set_sale_price( $sale_price );
				$course_bundle->set_price( $sale_price );
			} else {
				$course_bundle->set_price( $regular_price );
				$course_bundle->set_sale_price( '' );
			}

			if ( ! is_null( $regular_price ) || ! is_null( $sale_price ) ) {
				if ( ! empty( $currency ) && ! is_null( $currency ) ) {
					$course_bundle->set_currency( $currency );
				}
			}
		}

		return $course_bundle;
	}

	/**
	 * Modify group course price based on multiple currency settings.
	 *
	 * @since 1.17.1 [free]
	 *
	 * @param float $group_price Group course price.
	 * @param int   $course_id   Course ID.
	 *
	 * @return float
	 */
	public function modify_group_course_price( $group_price, $course_id ) {
		if ( ! masteriyo_string_to_bool( get_post_meta( $course_id, '_multiple_currency_enabled', true ) ) ) {
			return $group_price;
		}

		if ( ! masteriyo_is_single_course_page() ) {
			return $group_price;
		}

		list( $currency, $pricing_zone ) = masteriyo_get_currency_and_pricing_zone_based_on_course( $course_id );

		if ( empty( $currency ) ) {
			return $group_price;
		}

		$modified_group_price = masteriyo_get_country_based_group_course_price( $course_id, $group_price, $pricing_zone );

		return $modified_group_price ? $modified_group_price : $group_price;
	}

	/**
	 * Append multiple currency to course response.
	 *
	 * @since 1.11.0 [free]
	 *
	 * @param array $data Course data.
	 * @param \Masteriyo\Models\Course $course Course object.
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @param \Masteriyo\RestApi\Controllers\Version1\CoursesController $controller REST courses controller object.
	 *
	 * @return array
	 */
	public function append_multiple_currency_data_in_response( $data, $course, $context, $controller ) {

		if ( $course instanceof \Masteriyo\Models\Course ) {

			$active_zones = masteriyo_get_active_pricing_zone_data();

			$active_zones = array_map(
				function( $active_zone ) use ( $course ) {
					$pricing_method = get_post_meta( $course->get_id(), "_multiple_currency_{$active_zone['id']}_pricing_method", true );
					$regular_price  = masteriyo_format_decimal( get_post_meta( $course->get_id(), "_multiple_currency_{$active_zone['id']}_regular_price", true ) );
					$sale_price     = masteriyo_format_decimal( get_post_meta( $course->get_id(), "_multiple_currency_{$active_zone['id']}_sale_price", true ) );

					$group_price = masteriyo_format_decimal( get_post_meta( $course->get_id(), "_multiple_currency_{$active_zone['id']}_group_price", true ) );

					$enabled_key = "_multiple_currency__{$active_zone['id']}_enabled";
					$enabled     = metadata_exists( 'post', $course->get_id(), $enabled_key ) ? get_post_meta( $course->get_id(), $enabled_key, true ) : true;

					$active_zone['enabled']        = masteriyo_string_to_bool( $enabled );
					$active_zone['pricing_method'] = $pricing_method ? $pricing_method : 'exchange_rate';
					$active_zone['regular_price']  = $regular_price;
					$active_zone['sale_price']     = $sale_price;
					$active_zone['group_price']    = $group_price;

					return $active_zone;
				},
				$active_zones
			);

			$enabled = masteriyo_string_to_bool( get_post_meta( $course->get_id(), '_multiple_currency_enabled', true ) );

			$data['multiple_currency'] = array(
				'enabled'       => $enabled,
				'pricing_zones' => $active_zones,
			);
		}

		return $data;
	}

	/**
	 * Save multiple currency data.
	 *
	 * @since 1.11.0 [free]
	 *
	 * @param integer $id The course ID.
	 * @param \Masteriyo\Models\Course $object The course object.
	 */
	public function save_multiple_currency_data( $id, $course ) {
		$request = masteriyo_current_http_request();

		if ( null === $request ) {
			return;
		}
		if ( ! isset( $request['multiple_currency'] ) ) {
			return;
		}

		$active_zones = masteriyo_get_active_pricing_zone_data();

		if ( ! empty( $active_zones ) ) {
			foreach ( $active_zones as $active_zone ) {

				if ( isset( $request['multiple_currency']['enabled'] ) ) {
					update_post_meta( $id, '_multiple_currency_enabled', masteriyo_string_to_bool( $request['multiple_currency']['enabled'] ) );

					if ( isset( $request['multiple_currency'][ $active_zone['id'] . '_key' ] ) ) {

						$regular_price = '';
						$sale_price    = '';

						if ( isset( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['regular_price'] ) ) {
							$regular_price = masteriyo_format_decimal( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['regular_price'] );
						}

						if ( isset( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['sale_price'] ) ) {
							$sale_price = masteriyo_format_decimal( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['sale_price'] );
						}

						if ( isset( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['group_price'] ) ) {
							$group_price = masteriyo_format_decimal( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['group_price'] );
							update_post_meta( $id, "_multiple_currency_{$active_zone['id']}_group_price", $group_price );
						}

						if ( isset( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['enabled'] ) ) {
							update_post_meta( $id, "_multiple_currency__{$active_zone['id']}_enabled", masteriyo_string_to_bool( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['enabled'] ) );
						}

						if ( isset( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['pricing_method'] ) ) {
							update_post_meta( $id, "_multiple_currency_{$active_zone['id']}_pricing_method", sanitize_text_field( $request['multiple_currency'][ $active_zone['id'] . '_key' ]['pricing_method'] ) );
						}

						update_post_meta( $id, "_multiple_currency_{$active_zone['id']}_regular_price", $regular_price );

						$sale_price = '' !== $sale_price && (float) $regular_price > (float) $sale_price ? $sale_price : '';

						update_post_meta( $id, "_multiple_currency_{$active_zone['id']}_sale_price", $sale_price );
					}
				}
			}
		}
	}

	/**
	 * Add multiple currency fields to course schema.
	 *
	 * @since 1.11.0 [free]
	 *
	 * @param array $schema
	 * @return array
	 */
	public function add_multiple_currency_schema_to_course( $schema ) {
		$schema = wp_parse_args(
			$schema,
			array(
				'multiple_currency' => array(
					'description' => __( 'Multiple currency setting', 'learning-management-system' ),
					'type'        => 'object',
					'context'     => array( 'view', 'edit' ),
					'items'       => array(
						'type'       => 'object',
						'properties' => array(
							'enabled'        => array(
								'description' => __( 'Enable multiple currency.', 'learning-management-system' ),
								'type'        => 'boolean',
								'default'     => false,
								'context'     => array( 'view', 'edit' ),
								'readonly'    => true,
							),
							'pricing_method' => array(
								'description' => __( 'Maximum Group Size', 'learning-management-system' ),
								'type'        => 'string',
								'default'     => 'exchange_rate',
								'context'     => array( 'view', 'edit' ),
							),
							'regular_price'  => array(
								'description' => __( 'Course regular price.', 'learning-management-system' ),
								'type'        => 'string',
								'default'     => '',
								'context'     => array( 'view', 'edit' ),
							),
							'sale_price'     => array(
								'description' => __( 'Course sale price.', 'learning-management-system' ),
								'type'        => 'string',
								'default'     => '',
								'context'     => array( 'view', 'edit' ),
							),
						),
					),
				),
			)
		);

		return $schema;
	}

	/**
	 * Register REST API namespaces for the Group Courses.
	 *
	 * @since 1.9.0
	 *
	 * @param array $namespaces Rest namespaces.
	 *
	 * @return array Modified REST namespaces including Group Courses endpoints.
	 */
	public function register_rest_namespaces( $namespaces ) {
		$namespaces['masteriyo/v1']['multiple-currency-pricing-zones'] = PriceZonesController::class;
		$namespaces['masteriyo/v1']['multiple-currency-settings']      = MultipleCurrencySettingsController::class;

		return $namespaces;
	}

	/**
	 * Register price zone post types.
	 *
	 * @since 1.9.0
	 *
	 * @param string[] $post_types
	 *
	 * @return string[]
	 */
	public function register_price_zone_post_type( $post_types ) {
		$post_types[] = PriceZone::class;

		return $post_types;
	}

	/**
	 * Register multiple currency submenu.
	 *
	 * @since 1.9.0
	 *
	 * @param array $submenus Admin submenus.
	 *
	 * @return array
	 */
	public function register_multiple_currency_submenu( $submenus ) {
		$submenus['multiple-currency/pricing-zones'] = array(
			'page_title' => __( 'Multiple Currency', 'learning-management-system' ),
			'menu_title' => __( 'Multiple Currency', 'learning-management-system' ),
			'position'   => 63,
		);

		return $submenus;
	}
}
