<?php

namespace Discountify\Core\Frontend;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use Discountify\Utils\Singleton;

/**
 * Calculator Class
 *
 * @since 1.0.0
 */
class Rules extends Message {

	use Singleton;

	/**
	 * Discount price
	 */
	public function get_rules_type( $product_id ) {
		$response = array(
			'success' => false,
			'data'    => array(
				'rules_type'      => '',
				'discount_in'     => '',
				'products'        => array(),
				'categories'      => array(),
				'discount_type'   => '',
				'discount_number' => '',
			),
		);

		$rules_in  = \Discountify\Utils\Helper::rules_type( false, true );
		$all_rules = (array) \Discountify\Utils\Helper::get_all_rules();

		// Get the product object to check if it's a variation
		$product   = wc_get_product( $product_id );
		$parent_id = 0;

		// If it's a variation, get the parent ID
		if ( $product && $product->is_type( 'variation' ) ) {
			$parent_id = $product->get_parent_id();
		}

		foreach ( $all_rules  as $key => $value ) {

			if ( 'yes' !== $value['enable_rules'] ) {
				continue;
			}

			// Skip expired or user-restricted rules early so they don't overwrite valid ones.
			if ( ! $this->discount_period( $value ) ) {
				continue;
			}
			if ( ! $this->role_base_discount( $value ) ) {
				continue;
			}

			if ( in_array( $value['rules_type'], $rules_in ) ) {
				if ( 'product' === $value['discount_in'] ) {
					$discount_applies = false;

					// Check if the specific product/variation is in the filter
					if ( \Discountify\Utils\Helper::discount_product( $product_id, $value['filter_by_products'] ) === true ) {
						$discount_applies = true;
					}
					// If current product is a variation and parent is selected, apply discount to all variations
					elseif ( $parent_id > 0 && \Discountify\Utils\Helper::discount_product( $parent_id, $value['filter_by_products'] ) === true ) {
						$discount_applies = true;
					}

					if ( $discount_applies ) {
						$response['success']          = true;
						$response['data']             = $value;
						$response['data']['products'] = $value['filter_by_products'];
					}
				} elseif ( 'category' === $value['discount_in'] &&
				\Discountify\Utils\Helper::discount_category( $product_id, $value['filter_by_category'] ) === true ) {
					$response['success']            = true;
					$response['data']               = $value;
					$response['data']['categories'] = $value['filter_by_category'];
				} elseif ( $value['discount_in'] === 'all' ) {
					$response['success']          = true;
					$response['data']             = $value;
					$response['data']['products'] = array( $product_id );
				}
			}
		}

		return $response;
	}

	/**
	 * If product exist in bogo offer free
	 *
	 * @param [type] $bogo_discount_in
	 * @param [type] $product_id
	 * @param [type] $bogo_discounts
	 * @return bool
	 */
	public function product_exists_in( $bogo_discount_in, $product_id, $bogo_discounts ) {
		$result = false;

		if ( $bogo_discount_in === 'product' ) {
			$result = \Discountify\Utils\Helper::discount_product( $product_id, $bogo_discounts['bogo_x_y_products'] );
		} elseif ( $bogo_discount_in === 'category' ) {
			$result = \Discountify\Utils\Helper::discount_category( $product_id, $bogo_discounts['bogo_x_y_categories'] );
		}

		return $result;
	}


	/**
	 * Check rules
	 *
	 * @param [type] $rules
	 * @param [type] $quantity
	 * @param [type] $price
	 * @return array
	 */
	public function multi_discount_type( $rules, $quantity, $price ) {
		$result = array(
			'offer_type'            => '',
			'discount_number'       => '',
			'apply_discount_number' => '',
			'free_quantity'         => 0,
			'coupon'                => 0,
		);
		if ( empty( $rules['multi_discounts'] ) ) {
			return $result;
		}

		foreach ( $rules['multi_discounts'] as $key => $value ) {
			$max     = (int) $key + 1;
			$get_max = ! empty( $rules['multi_discounts'][ $max ]['min'] ) ? $rules['multi_discounts'][ $max ]['min'] : 9999;
			if ( ( $quantity >= $value['min'] ) && ( $quantity < $get_max ) ) {
				$value['apply_discount_number'] = $value['discount_number'];
				$value['coupon']                = true;
				if ( in_array( $rules['bogo_discount_type'], array( 'buy_x_get_y', 'category_bogo' ), true ) ) {
					$value['coupon'] = false;
					if ( 'free' === $value['offer_type'] ) {
						$value['if_exist_delete'] = $this->free_deletable_pro( $rules, $rules['multi_discounts'], true );
						$value['coupon']          = false;

						return $value;
					} else {
						$value['free_deletable_pro'] = $this->free_deletable_pro( $rules, $rules['multi_discounts'] );

						return $value;
					}
				} else {
					$free_qty        = $value['free_quantity'] === '' ? $quantity : $value['free_quantity'];
					$discount_number = $value['discount_number'] === '' ? 0 : (float) $value['discount_number'];

					if ( $value['offer_type'] === 'free' ) {
						$value['apply_offer']     = 'fixed_cart';
						$value['discount_number'] = (int) $free_qty * $price;

						return $value;
					} elseif ( $value['offer_type'] === 'percentage' ) {
						$value['apply_offer']     = 'fixed_cart';
						$value['discount_number'] = 1 * $price * ( $discount_number / 100 );

						return $value;
					} elseif ( $value['offer_type'] === 'fixed' ) {
						$value['apply_offer'] = 'fixed_cart';
						if ( isset( $rules['bogo_discount_type'] ) && $rules['bogo_discount_type'] === 'bogo_fixed_price' ) {
							// bogo_fixed_price: discount_number is the target price, not discount amount
							$discounted_qty             = $free_qty > 0 ? 1 : 0;
							$value['discount_number']   = ( $price - $discount_number ) * $discounted_qty;
						} else {
							$value['discount_number'] = (int) $free_qty * $discount_number;
						}
						return $value;
					}
				}
			}
		}

		return $result;
	}

	/**
	 * Get bogo free products
	 *
	 * @param [type] $bogo_discounts
	 * @return array
	 */
	public function free_deletable_pro( $rules, $bogo_discounts, $check_delete = false ) {
		$free_products = array();
		foreach ( $bogo_discounts as $key => $value ) {
			if ( 'free' === $value['offer_type'] ) {
				if ( 'product' === $rules['bogo_discount_in'] ) {
					$free_products = $value['bogo_x_y_products'];
					foreach ( $value['bogo_x_y_products'] as $key => $item ) {
						array_push( $free_products, $item );
					}
				} elseif ( 'category' === $rules['bogo_discount_in'] ) {
					foreach ( $value['bogo_x_y_categories'] as $key => $id ) {
						$products = \Discountify\Utils\Helper::products_category( $id );
						foreach ( $products as $key => $item ) {
							array_push( $free_products, $item );
						}
					}
				}
			} elseif ( 'free' !== $value['offer_type'] && true === $check_delete ) {
				if ( 'product' === $rules['bogo_discount_in'] ) {
					$free_products = $value['bogo_x_y_products'];
					foreach ( $value['bogo_x_y_products'] as $key => $item ) {
						array_push( $free_products, $item );
					}
				} elseif ( 'category' === $rules['bogo_discount_in'] ) {
					foreach ( $value['bogo_x_y_categories'] as $key => $id ) {
						$products = \Discountify\Utils\Helper::products_category( $id );
						foreach ( $products as $key => $item ) {
							array_push( $free_products, $item );
						}
					}
				}
			}
		}

		return $free_products;
	}

	/**
	 * Cart total spend
	 *
	 * @param [type] $discounts
	 * @return array
	 */
	public function total_spend( $discounts, $price ) {
		$result = array();
		foreach ( $discounts as $key => $value ) {
			$max     = (int) $key + 1;
			$get_max = ! empty( $discounts['multi_discounts'][ $max ]['min'] ) ? $discounts['multi_discounts'][ $max ]['min'] : 9999;
			if ( ( $price >= $value['min'] ) && ( $price < $get_max ) ) {
				$value['discount_type'] = $value['offer_type'] === 'percentage' ? 'percent' : 'fixed_cart';
				$result                 = $value;
			}
		}

		return $result;
	}

	/**
	 * Bogo buy x get y products
	 *
	 * @param [type] $bogo_discount_in
	 * @param [type] $bogo_discounts
	 * @return array
	 */
	public function get_bogo_products( $bogo_discount_in, $bogo_discounts ) {
		$products = array();
		if ( 'product' === $bogo_discount_in ) {
			$raw = ! empty( $bogo_discounts['bogo_x_y_products'] ) ? (array) $bogo_discounts['bogo_x_y_products'] : array();
			// Return ['all'] as-is so callers can detect the "all products" case.
			$products = $raw;
		} else {
			$categories = ! empty( $bogo_discounts['bogo_x_y_categories'] ) ? (array) $bogo_discounts['bogo_x_y_categories'] : array();
			if ( in_array( 'all', $categories, true ) ) {
				$products = array( 'all' );
			} else {
				foreach ( $categories as $id ) {
					$products = array_merge( $products, \Discountify\Utils\Helper::products_category( $id ) );
				}
			}
		}

		return $products;
	}

	public function bogo_x_y_offer_check( $cart_item ) {
		$bogo_x_y = array();
		$msg      = array();
		// Use variation_id if it exists, otherwise use product_id
		$product_id  = ! empty( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : $cart_item['product_id'];
		$result      = $this->get_rules_type( $product_id );
		$result_data = $result['data'];
		$data        = $this->multi_discount_type( $result_data, $cart_item['quantity'], $cart_item['data']->get_price() );

		if ( $result_data['rules_type'] === 'bogo' &&
		in_array( $result_data['bogo_discount_type'], array( 'buy_x_get_y', 'category_bogo' ), true ) ) {
			if ( 'percentage' === $data['offer_type'] || 'fixed' === $data['offer_type'] ) {
				$bogo_x_y ['bogo_x_y_discount'] = $this->get_bogo_products( $result_data['bogo_discount_in'], $data );
				$bogo_x_y ['free_qty']          = $data['free_quantity'] === '' ? $cart_item['quantity'] : $data['free_quantity'];
				$bogo_x_y ['offer_type']        = $data['offer_type'];
				$bogo_x_y ['discount_number']   = $data['discount_number'];
			}
		}

		if ( ! empty( $bogo_x_y ) ) {
			global $woocommerce;
			$ful_msg = '';
			foreach ( $woocommerce->cart->get_cart() as $cart_key => $cart_data ) {
				if ( is_array( $bogo_x_y['bogo_x_y_discount'] ) && in_array( $cart_data['data']->get_id(), $bogo_x_y['bogo_x_y_discount'] ) ) {
					$msg['msg_label'] = esc_html__( 'Offer', 'discountify' );
					if ( 'fixed' === $bogo_x_y['offer_type'] ) {
						$discount_str = get_woocommerce_currency_symbol() . (float) $bogo_x_y['discount_number'] . ' ' . esc_html__( 'off', 'discountify' );
					} elseif ( 'percentage' === $bogo_x_y['offer_type'] ) {
						$discount_str = (float) $bogo_x_y['discount_number'] . '% ' . esc_html__( 'off', 'discountify' );
					} else {
						$discount_str = '';
					}
					$ful_msg .= $discount_str . ' · ' . esc_html( $cart_data['data']->get_name() ) . '<br/>';
				}
			}
			$msg['message'] = $ful_msg;
		}

		return $msg;
	}

	protected function discount_period( $rule ) {
		$apply_discount = true;
		if ( empty( $rule['discount_valid'] ) ) {
			return $apply_discount;
		}

		// Use ' - ' (with spaces) to split date range, not just '-' which breaks dates like 2024-01-15
		$valid_period = explode( ' - ', $rule['discount_valid'] );
		if ( count( $valid_period ) !== 2 || empty( trim( $valid_period[0] ) ) || empty( trim( $valid_period[1] ) ) ) {
			return $apply_discount;
		}

		$start_date   = strtotime( trim( $valid_period[0] ) );
		$end_date     = strtotime( trim( $valid_period[1] ) );
		$current_time = strtotime( wp_date( 'Y-m-d' ) );

		// Check if dates are valid
		if ( $start_date === false || $end_date === false ) {
			return $apply_discount;
		}

		if ( $current_time < $start_date || $current_time > $end_date ) {
			$apply_discount = false;
		}

		return $apply_discount;
	}

	/**
	 * Check user role
	 *
	 * @param [type] $rule
	 * @return bool
	 */
	protected function role_base_discount( $rule ) {
		$apply_discount = true;
		if ( empty( $rule['enable_user_discount'] ) ||
		( ! empty( $rule['enable_user_discount'] ) && $rule['enable_user_discount'] !== 'yes' )
		) {
			return $apply_discount;
		}

		if ( $rule['user_discount_condition'] === 'user_roles' ) {
			if ( is_user_logged_in() ) {
				$current_user = wp_get_current_user();
				$user_roles   = $current_user->roles;
				if ( is_array( $rule['disc_user_roles'] ) ) {
					$apply_discount = ! empty( array_intersect( $rule['disc_user_roles'], $user_roles ) );
				} else {
					$apply_discount = in_array( $rule['disc_user_roles'], $user_roles );
				}

				return $apply_discount;

			} else {
				$apply_discount = false;
			}
		} elseif ( $rule['user_discount_condition'] === 'specific_customers' ) {
			if ( is_user_logged_in() ) {
				$user_id = get_current_user_id();
				if ( is_array( $rule['specific_customers'] ) ) {
					$apply_discount = in_array( $user_id, $rule['specific_customers'] ) ? true : false;
				} else {
					$apply_discount = (int) $rule['specific_customers'] === $user_id ? true : false;
				}

				return $apply_discount;

			} else {
				$apply_discount = false;
			}
		}

		return $apply_discount;
	}
}
