<?php

namespace EDPW\Core\Helpers;

use Exception;
use Pelago\Emogrifier\CssInliner;
use WC_Emails;
use WC_Order;
use WC_Order_Refund;

defined( 'ABSPATH' ) || exit;

class WC {
	public static $instance = null;

	public static function getInstance() {
		if ( ! self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Has admin privilege.
	 *
	 * @return bool
	 */
	public static function hasAdminPrivilege(): bool {
		//return current_user_can( 'manage_woocommerce' );
		return current_user_can( 'manage_options' );
	}

	/**
	 * Verify nonce.
	 *
	 * @param string $nonce Nonce.
	 * @param string $action Action.
	 *
	 * @return bool
	 */
	public static function verifyNonce( string $nonce, string $action = '' ): bool {
		if ( empty( $nonce ) || empty( $action ) ) {
			return false;
		}

		return wp_verify_nonce( $nonce, $action );
	}

	/**
	 * Check the validity of a security nonce and the admin privilege.
	 *
	 * @param string $nonce_name The name of the nonce.
	 *
	 * @return bool
	 */
	public static function isSecurityValid( string $nonce_name = '' ): bool {
		$wdr_nonce = Input::get( 'edpw_nonce' );
		if ( ! self::hasAdminPrivilege() || ! self::verifyNonce( $wdr_nonce, $nonce_name ) ) {
			return false;
		}

		return true;
	}

	/**
	 * Create nonce for woocommerce.
	 *
	 * @param string $action
	 *
	 * @return false|string
	 */
	public static function createNonce( string $action = '' ) {
		if ( empty( $action ) ) {
			return false;
		}

		return wp_create_nonce( $action );
	}

	/**
	 * Add admin notice.
	 *
	 * @param string $message Message.
	 * @param string $status Status.
	 *
	 * @return void
	 */
	public static function adminNotice( string $message, string $status = "success" ) {
		add_action( 'admin_notices', function () use ( $message, $status ) {
			?>
            <div class="notice notice-<?php echo esc_attr( $status ); ?>">
                <p><?php echo wp_kses_post( $message ); ?></p>
            </div>
			<?php
		}, 1 );
	}

	/**
	 * Get all available language.
	 *
	 * @return array
	 */
	public static function getAvailableLanguages() {
		if ( ! function_exists( 'get_available_languages' ) ) {
			return [];
		}

		$return_languages = get_available_languages();
		if ( ! in_array( 'en_US', $return_languages ) ) {
			array_unshift( $return_languages, 'en_US' );
		}

		$available_languages = [];
		foreach ( $return_languages as $language ) {
			$available_languages[] = [ 'label' => self::getLanguageLabel( $language ), 'value' => $language ];
		}
		//phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
		$wpml_available_languages = apply_filters( 'wpml_active_languages', null, [] );
		if ( ! empty( $wpml_available_languages ) && is_array( $wpml_available_languages ) ) {
			foreach ( $wpml_available_languages as $lang_code => $language ) {
				$key_exists = false;
				foreach ( $available_languages as $check_language ) {
					// Check if the key exists in the current sub-array
					if ( isset( $check_language['value'] ) && $check_language['value'] === $language['default_locale'] ) {
						$key_exists = true;
						break; // Exit the loop since the key is found
					}
				}
				if ( ! $key_exists ) {
					$available_languages[] = [
						'label' => ( ! empty( $language['native_name'] ) ) ? $language['native_name'] : $lang_code,
						'value' => ( ! empty( $language['default_locale'] ) ) ? $language['default_locale'] : $lang_code
					];
				}
			}
		}

		return apply_filters( 'edpw_get_available_languages', $available_languages );
	}


	public static function getLanguageLabel( $language_code ) {
		$label        = '';
		$translations = self::getWpAvailableTranslations();
		if ( isset( $translations[ $language_code ]['native_name'] ) ) {
			$label = $translations[ $language_code ]['native_name'];
		} else {
			foreach ( $translations as $lang_code => $lang_details ) {
				if ( isset( $lang_details['iso'] ) && is_array( $lang_details['iso'] ) && in_array( $language_code, $lang_details['iso'] ) ) {
					$label = $lang_details['native_name'];
					break;
				}
			}
			if ( empty( $label ) && ( $language_code == 'en_US' || $language_code == 'en' || $language_code == 'en_GB' ) ) {
				$label = "English";
			} elseif ( empty( $label ) ) {
				$label = $language_code . "(Name unknown)";
			}
		}

		return apply_filters( "edpw_get_language_label", $label, $language_code );
	}

	public static function getWpAvailableTranslations() {
		require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
		if ( function_exists( 'wp_get_available_translations' ) ) {
			return wp_get_available_translations();
		}

		return [];
	}

	/**
	 * Get site's default language.
	 *
	 * @return string
	 */
	public static function getSiteDefaultLang() {
		$current_lang = 'en_US';
		if ( function_exists( 'get_locale' ) ) {
			$current_lang = get_locale();
			if ( empty( $current_lang ) || $current_lang == 'en' ) {
				$current_lang = 'en_US';
			}
		}

		return $current_lang;
	}

	/**
	 * Check method exists in object.
	 *
	 * @param object $obj Given object.
	 * @param string $method Method name.
	 *
	 * @return bool
	 */
	public static function isMethodExists( $obj, $method ): bool {
		if ( is_object( $obj ) && method_exists( $obj, $method ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Get mailer emails.
	 *
	 * @return array|WC_Emails
	 */
	public static function getMailer() {
		if ( function_exists( 'WC' ) ) {
			if ( self::isMethodExists( WC(), 'mailer' ) ) {
				return WC()->mailer();
			}
		}

		return [];
	}

	/**
	 * Get order.
	 *
	 * @param mixed $the_order Order id or Order object.
	 *
	 * @return bool|WC_Order|WC_Order_Refund
	 */
	public static function getOrder( $the_order ) {
		return wc_get_order( $the_order );
	}

	/**
	 * Get order id.
	 *
	 * @param mixed $the_order Order id or order object.
	 *
	 * @return false|int
	 */
	public static function getOrderId( $the_order ) {
		$order = self::getOrder( $the_order );
		if ( self::isMethodExists( $order, 'get_id' ) ) {
			return $order->get_id();
		}

		return false;
	}

	/**
	 * Get order meta.
	 *
	 * @param WC_Order $order Order object.
	 * @param string $meta_key Order meta key.
	 *
	 * @return mixed|null
	 */
	public static function getOrderMeta( $order, $meta_key ) {
		$meta_value = null;
		if ( self::isMethodExists( $order, 'get_meta' ) ) {
			$meta_value = $order->get_meta( $meta_key );
		}

		return $meta_value;
	}

	/**
	 * Get WPML languages.
	 *
	 * @return array
	 */
	public static function getWPMLLanguages() {
		$languages = [];
		if ( function_exists( 'icl_get_languages' ) ) {
			$languages = icl_get_languages();
		}

		return $languages;
	}

	/**
	 * Get order address data.
	 *
	 * @param string $key Method name.
	 * @param object $object Order object.
	 *
	 * @return mixed|null
	 */
	public static function getOrderData( $key, $object, $default = null ) {
		if ( empty( $key ) ) {
			return null;
		}
		$method_name = "get_" . $key;

		return self::isMethodExists( $object, $method_name ) ? $object->$method_name() : $default;
	}

	/**
	 * Get
	 *
	 * @param $country
	 *
	 * @return array|false
	 */
	public static function getStates( $country ) {
		if ( function_exists( 'WC' ) && self::isMethodExists( WC()->countries, 'get_states' ) ) {
			return WC()->countries->get_states( $country );
		}

		return [];
	}

	/**
	 * Get country.
	 *
	 * @param string $country Country code.
	 *
	 * @return string
	 */
	public static function getCountry( $country ) {
		if ( function_exists( 'WC' ) && isset( WC()->countries->countries[ $country ] ) ) {
			return WC()->countries->countries[ $country ];
		}

		return '';
	}

	/**
	 * Format price.
	 *
	 * @param float $price Raw price.
	 *
	 * @return string
	 */
	public static function formatPrice( $price ) {
		if ( function_exists( 'wc_price' ) ) {
			return wc_price( $price );
		}

		return $price;
	}

	/**
	 * Is support Emogrifier.
	 *
	 * @return bool
	 */
	protected static function supportsEmogrifier() {
		return class_exists( 'DOMDocument' ) && version_compare( PHP_VERSION, '5.5', '>=' );
	}

	/**
	 * Css convert to inline style.
	 *
	 * @param string $content Email content.
	 * @param string $css Email css.
	 *
	 * @return string
	 */
	public static function styleInline( $content, $css ) {
		if ( empty( $css ) || empty( $content ) ) {
			return $content;
		}
		try {
			if ( self::supportsEmogrifier() ) {
				$content = apply_filters( 'edpw_before_inline_style_content', $content );
				$css     = apply_filters( 'edpw_before_inline_style_css', $css );
				if ( apply_filters( 'edpw_need_inline_style', true ) && class_exists( CssInliner::class ) ) {
					$content = CssInliner::fromHtml( $content )->inlineCss( $css )->render();
				}
				$content = apply_filters( 'edpw_after_inline_style_content', $content );
			}
		} catch ( Exception $e ) {

		}

		return $content;
	}

	/**
	 * Is download permitted.
	 *
	 * @param WC_Order $order Order object.
	 *
	 * @return bool
	 */
	public static function isOrderDownLoadPermitted( $order ) {
		if ( self::isMethodExists( $order, 'is_download_permitted' ) ) {
			return $order->is_download_permitted();
		}

		return false;
	}

	/**
	 * Is order paid.
	 *
	 * @param WC_Order $order Order object.
	 *
	 * @return bool
	 */
	public static function isOrderPaid( $order ) {
		if ( self::isMethodExists( $order, 'is_paid' ) ) {
			return $order->is_paid();
		}

		return false;
	}

	/**
	 * Get order items.
	 *
	 * @param WC_Order $order Order object.
	 *
	 * @return array
	 */
	public static function getOrderItems( $order ) {
		if ( self::isMethodExists( $order, 'get_items' ) ) {
			return $order->get_items();
		}

		return [];
	}

	public static function getOrderItemsCount( $order ) {
		if ( self::isMethodExists( $order, 'get_item_count' ) ) {
			return $order->get_item_count();
		}

		return [];
	}

	/**
	 * Get product.
	 *
	 * @param object $item line item.
	 *
	 * @return array|mixed
	 */
	public static function getProduct( $item ) {
		if ( self::isMethodExists( $item, 'get_product' ) ) {
			return $item->get_product();
		}

		return null;
	}

	/**
	 * Get item image id.
	 *
	 * @param object $item line item.
	 *
	 * @return int|mixed
	 */
	public static function getItemImageId( $item ) {
		if ( self::isMethodExists( $item, 'get_image_id' ) ) {
			return $item->get_image_id();
		}

		return 0;
	}

	/**
	 * Get placeholder image.
	 *
	 * @return string|null
	 */
	public static function getPlaceHolderImage() {
		if ( function_exists( 'wc_placeholder_img_src' ) ) {
			return wc_placeholder_img_src();
		}

		return null;
	}

	/**
	 * Get item name.
	 *
	 * @param object $item line item.
	 *
	 * @return array|mixed
	 */
	public static function getItemName( $item ) {
		if ( self::isMethodExists( $item, 'get_name' ) ) {
			return $item->get_name();
		}

		return [];
	}

	/**
	 * Get item quantity.
	 *
	 * @param object $item Line item.
	 *
	 * @return int
	 */
	public static function getItemQuantity( $item ) {
		if ( self::isMethodExists( $item, 'get_quantity' ) ) {
			return $item->get_quantity();
		}

		return 0;
	}

	/**
	 * Get order line subtotal.
	 *
	 * @param WC_Order $order Order object
	 * @param object $item Item to get total from.
	 *
	 * @return string
	 */
	public static function getOrderLineSubTotal( $order, $item ) {
		if ( self::isMethodExists( $order, 'get_formatted_line_subtotal' ) ) {
			return $order->get_formatted_line_subtotal( $item );
		}

		return '';
	}

	/**
	 * Has download item.
	 *
	 * @param WC_Order $order Order object.
	 *
	 * @return bool
	 */
	public static function hasDownloadableItem( $order ) {
		if ( self::isMethodExists( $order, 'has_downloadable_item' ) ) {
			return $order->has_downloadable_item();
		}

		return false;
	}

	/**
	 * Is download permitted.
	 *
	 * @param WC_Order $order Order object.
	 *
	 * @return bool
	 */
	public static function isDownloadPermitted( $order ) {
		if ( self::isMethodExists( $order, 'is_download_permitted' ) ) {
			return $order->is_download_permitted();
		}

		return false;
	}

	/**
	 * Get order meta data.
	 *
	 * @param mixed $the_order Order id or object.
	 *
	 * @return array
	 */
	public static function getOrderMetaData( $the_order ) {
		$order = self::getOrder( $the_order );

		return self::isMethodExists( $order, 'get_meta_data' ) ? $order->get_meta_data() : [];//wp_list_pluck($order->get_meta_data(), 'key');
	}

	public static function getOrderLabel( $order_id ) {
		$order = self::getOrder( $order_id );
		$label = self::getOrderData( 'order_number', $order ) . ' - ' . self::getOrderData( 'billing_first_name', $order ) . ' ' . self::getOrderData( 'billing_last_name', $order );

		return apply_filters( 'edpw_get_sample_order_label', $label, $order );
	}

	public static function getDateFormat() {
		return apply_filters( 'edpw_date_format', get_option( 'date_format' ) );
	}
}