<?php
namespace BricksUltimate;

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

use BricksUltimate\{Plugin, Helpers};
use BricksUltimate\Admin\License;

class Compare {
	public static $instance = null;
	public static $compare_ids = [];
	public static $key = 'bu-compare';
	public static $inited = false;
	public $base_url = '';
	public static $cmp_cookie_key = '';

	/**
	 * Saves compare item ids in cookie
	 */
	const COOKIE_KEY = 'bu_compare';

	public function __construct() {
		if ( License::has_valid_license() ) {
			add_action( 'wp_ajax_bu_update_compare_items', [ $this, 'update_compare_items' ] );
			add_action( 'wp_ajax_nopriv_bu_update_compare_items', [ $this, 'update_compare_items' ] );
			add_action( 'wp_ajax_bu_delete_compare_item', [ $this, 'delete_compare_item' ] );
			add_action( 'wp_ajax_nopriv_bu_delete_compare_item', [ $this, 'delete_compare_item' ] );
			add_action( 'wp_ajax_bu_mini_compare', [ $this, 'bu_mini_compare' ] );
			add_action( 'wp_ajax_nopriv_bu_mini_compare', [ $this, 'bu_mini_compare' ] );
			add_action( 'wp_ajax_bu_refresh_compare_table', [ $this, 'bu_refresh_compare_table' ], 30 );
			add_action( 'wp_ajax_nopriv_bu_refresh_compare_table', [ $this, 'bu_refresh_compare_table' ], 30 );
			add_filter( "bricks/elements/block/control_groups", array( $this, 'add_mini_compare_control_groups' ) );
			add_filter( "bricks/elements/block/controls", [ $this, 'add_mini_compare_controls' ] );
			add_filter( 'bricks/element/render_attributes', [ $this, 'bu_add_attributes' ], 1010, 3 );

			$this->init_actions();
		}
	}

	public function bu_add_attributes( $atts, $key, $element ) {
		$settings = $element->settings;
		if( $element->name == 'block' && !empty( $settings['isMiniCompWrapper'] ) ) {
			$atts['_root']['data-base-url'] = get_permalink( $element->post_id );
			$atts['_root']['data-element-id'] = $element->id;
			$atts['_root']['data-post-id'] = $element->post_id;
			$atts['_root']['class'][] = 'bu-mini-compare';
			if( ! empty( $settings['compHideContent'] ) ) {
				$atts['_root']['data-hide-content'] = "yes";
				$atts['_root']['data-content-selectors'] = $settings['compcntSelectors'] ?? 'no';
			}
		}

		return $atts;
	}

	public function add_mini_compare_control_groups( $control_groups ) {
		$control_groups['minicomp'] = [
			'tab'      => 'style',
			'title'    => esc_html__( 'Mini Compare', 'bricksultimate' ),
		];

		return $control_groups;
	}

	public function add_mini_compare_controls( $controls ) {
		$controls['isMiniCompWrapper'] = [
			'tab' 		=> 'style',
			'group' 	=> 'minicomp',
			'type'      => 'checkbox',
			'label'     => esc_html__( 'Using for Mini Compare Builder?', 'bricksultimate' ),
			'reset' 	=> true,
		];

		$controls['compHideContent'] = [
			'tab' 		=> 'style',
			'group' 	=> 'minicomp',
			'type'      => 'checkbox',
			'label'     => esc_html__( 'Hide contents when compare is empty', 'bricksultimate' ),
			'reset' 	=> true,
			'inline' 	=> false
		];

		$controls['compcntSelectors'] = [
			'tab' 		=> 'style',
			'group' 	=> 'minicomp',
			'type'        => 'text',
			'label'       => esc_html__( 'Content selectors', 'bricksultimate' ),
			'placeholder' => '.brxe-button',
			'required' 	=> ['compHideContent', '=', true]
		];

		return $controls;
	}

	public function update_compare_items() {
		check_ajax_referer( 'compare-nonce', 'security' );

		$data = ['success' => false];

		global $postData;

		$postData = [];
		$postId 	= $_POST['productId'];
		$postType 	= $_POST['postType'];
		$template_id = intval( $_POST['notice'] );
		$action 	= $_POST['compaction'];
		$cookie_key = $_POST['cookieKey'];
		$all_products = $this->get_compare_items( $cookie_key, $postType );
		self::$compare_ids[ $postType ] = isset( $all_products[ $postType ] ) ? $all_products[ $postType ] : [];

		if( ! in_array( $postId, self::$compare_ids[ $postType ] ) && $action == 'add' ) {
			$all_products[ $postType ][] = $postId;
			$data['success'] = true;
			$data['count'] = count( $all_products[ $postType ] );

			if( $template_id > 0 ) {
				$postData['id'] = $postId;
				$postData['filterType'] = 'notice';
				
				add_filter( 'bricks/posts/query_vars', [ '\BricksUltimate\Ajax', 'filter_query_args' ], 10, 3 );

				$elements = get_post_meta( $template_id, BRICKS_DB_PAGE_CONTENT, true );
				$template_inline_css = \Bricks\Templates::generate_inline_css( $template_id, $elements );

				$css = "<style id=\"bricks-inline-css-template-{$template_id}\">{$template_inline_css}</style>";

				$data['notice'] = do_shortcode('[bricks_template id="'. $template_id .'"]') . $css ;
				remove_filter( 'bricks/posts/query_vars', [ '\BricksUltimate\Ajax', 'filter_query_args' ], 10, 3 );
			}
		} elseif( in_array( $postId, self::$compare_ids[ $postType ] ) && $action == 'add' ) {
			$data['success'] = true;
			$data['count'] = count( $all_products[ $postType ] );
		}

		if( in_array( $postId, self::$compare_ids[ $postType ] ) && $action == 'delete' ) {
			if( ( $key = array_search($postId, $all_products[ $postType ]) ) !== false )
				unset($all_products[ $postType ][$key]);

			$data['success'] = true;
			$data['count'] = ($all_products[ $postType ]) ? count( $all_products[ $postType ] ) : 0;
		}

		if( $data['success'] ) {
			Plugin::bu_setcookie($cookie_key, implode(',', $all_products[ $postType ]), time() + ($this->get_days_cache() * WEEK_IN_SECONDS) );

			if( is_user_logged_in() ) {
				update_user_meta( get_current_user_id(), $cookie_key, implode(',', $all_products[ $postType ]) );

				Plugin::bu_setcookie($cookie_key, '', time() + ($this->get_days_cache() * WEEK_IN_SECONDS) );
				unset( $_COOKIE[$cookie_key] );
			}

			self::$compare_ids[ $postType ] = $all_products[ $postType ];
		}

		wp_send_json( $data );

		wp_die();
	}

	public function bu_mini_compare() {
		check_ajax_referer( 'compare-nonce', 'security' );

		$element_id = $_POST['element'];
		$post_id = isset( $_POST['post'] ) ? $_POST['post'] : 0;
		$this->base_url = isset( $_POST['base_url'] ) ? $_POST['base_url'] : '';

		add_filter(
			'bricks/paginate_links_args',
			function( $args ) {
				$args['base'] = $this->base_url . '%_%';
				return $args;
			}
		);

		$data = \Bricks\Helpers::get_element_data( $post_id, $element_id );

		// Prepare flat list of elements for recursive calls
		foreach ( $data['elements'] as $element ) {
			\Bricks\Frontend::$elements[ $element['id'] ] = $element;
		}

		$element_instance = new \Bricks\Element_Block( $data['element'] );
		$compare = \Bricks\Frontend::render_children( $element_instance );

		wp_send_json(
			array(
				'fragments' => apply_filters(
					'bu_update_mini_compare',
					array(
						'.bu-mini-compare' => $compare
					)
				),
			)
		);
	}

	public function bu_refresh_compare_table() {
		check_ajax_referer( 'compare-nonce', 'security' );

		$element_id = $_POST['element'];
		$post_id = isset( $_POST['post'] ) ? $_POST['post'] : 0;

		$data = \Bricks\Helpers::get_element_data( $post_id, $element_id );
		$output = \Bricks\Frontend::render_element( $data['element'] );

		wp_send_json(
			array(
				'fragments' => array(
					".brxe-{$element_id}" => $output
				)
			)
		);
	}

	public function delete_compare_item() {
		check_ajax_referer( 'compare-nonce', 'security' );

		$data = ['success' => true];

		$postId 	= $_POST['postId'];
		$postType 	= $_POST['postType'];
		$cookie_key = $this->get_cookie_key( $postType );
		$all_products = $this->get_compare_items( $cookie_key, $postType );
		self::$compare_ids[ $postType ] = isset( $all_products[ $postType ] ) ? $all_products[ $postType ] : [];

		if( in_array( $postId, self::$compare_ids[ $postType ] ) ) {
			if( ( $key = array_search($postId, $all_products[ $postType ]) ) !== false )
				unset($all_products[ $postType ][$key]);

			$data['success'] = true;
			$data['count'] = ($all_products[ $postType ]) ? count( $all_products[ $postType ] ) : 0;
		}

		if( $data['success'] ) {
			Plugin::bu_setcookie($cookie_key, implode(',', $all_products[ $postType ]), time() + ($this->get_days_cache() * WEEK_IN_SECONDS) );

			if( is_user_logged_in() ) {
				update_user_meta( get_current_user_id(), $cookie_key, implode(',', $all_products[ $postType ]) );

				Plugin::bu_setcookie($cookie_key, '', time() + ($this->get_days_cache() * WEEK_IN_SECONDS) );
				unset( $_COOKIE[$cookie_key] );
			}

			self::$compare_ids[ $postType ] = $all_products[ $postType ];
		}

		wp_send_json( $data );

		wp_die();
	}

	public function set_compare_items( $cookie_key = null, $type = 'post', $user_id = null ) {
		$compare_ids = [];

		$cached_products = '';
		$user_cached_products = false;

		if ( $user_id ) {
			$cached_products = get_user_meta( $user_id, $cookie_key, true );
			$user_cached_products = true;
		} elseif ( is_user_logged_in() ) {
			$cached_products = get_user_meta( get_current_user_id(), $cookie_key, true );
			$user_cached_products = true;
		}

		if ( !$user_cached_products && isset( $_COOKIE[ $cookie_key ] ) && !empty( $_COOKIE[ $cookie_key ] ) ) {
			$cached_products = $_COOKIE[ $cookie_key ];
		}

		if ( $cached_products != '' ) {
			$items = explode( ',', $cached_products);

			foreach( $items as $key => $product_id ) {
				if( ( 'product' == get_post_type( $product_id )  || 'product_variation' == get_post_type( $product_id ) ) && class_exists('WooCommerce') ) {
					$product = wc_get_product( $product_id );

					if( ! $product )
						continue;

					if( ! $product->exists() || 'trash' === $product->get_status() ) {
						continue;
					}

					$compare_ids[ $type ][] = $product_id;
				} elseif ( 'publish' === get_post_status( $product_id ) && $type == get_post_type( $product_id ) ) {
					$compare_ids[ $type ][] = $product_id;
				}
			}
		}

		return $compare_ids;
	}

	public function get_compare_items($cookie_key = null, $post_type = 'post', $user_id = null) {
		if( $cookie_key ) {
			return $this->set_compare_items( $cookie_key, $post_type );
		} else {
			$postTypes = \Bricks\Helpers::get_registered_post_types();

			if( $postTypes ) {
				$ids = [];
				foreach( $postTypes as $type => $label ) {
					$cookie_key = $this->get_cookie_key( $type );
					if( isset( $_COOKIE[ $cookie_key ] ) && !empty( $_COOKIE[ $cookie_key ] ) ) {
						$ids[ $type ] = isset( $this->set_compare_items( $cookie_key, $type )[ $type ] ) ? $this->set_compare_items( $cookie_key, $type )[ $type ] : [];
					} elseif( is_user_logged_in() && metadata_exists( 'user', get_current_user_id(), $cookie_key )) {
						$ids[ $type ] = isset( $this->set_compare_items( $cookie_key, $type )[ $type ] ) ? $this->set_compare_items( $cookie_key, $type )[ $type ] : [];
					}
				}

				return $ids;
			} else {
				return $this->set_compare_items( $cookie_key, $post_type );
			}
		}
    }

    public function save_user_compare_items( $type = 'post', $user_id = null, $cookie_key = null, $compare_ids = [] ) {
    	$saved_products = get_user_meta($user_id, $cookie_key, true);

		if ( $saved_products ) {
			$saved_products = explode(',', $saved_products);
		} else {
			$saved_products = [];
		}

		$ready_products = array_unique( array_merge( $saved_products, $compare_ids ) );

		foreach( $ready_products as $key => $product_id ) {
			if ( 'publish' !== get_post_status( $product_id ) && $type == get_post_type( $product_id ) ) {
				unset( $ready_products[ $key ] );
			} elseif( ( 'product' == get_post_type( $product_id )  || 'product_variation' == get_post_type( $product_id ) ) && class_exists('WooCommerce') ) {
				
				$product = wc_get_product( $product_id );

				if( ! $product || ! $product->exists() || 'trash' === $product->get_status() ) {
					unset( $ready_products[ $key ] );
				}
			}
		}

		update_user_meta($user_id, $cookie_key, implode(',', (array) $ready_products) );

		Plugin::bu_setcookie($cookie_key, '', time() + ($this->get_days_cache() * WEEK_IN_SECONDS));
		unset( $_COOKIE[$cookie_key] );
		self::$compare_ids[ $type ] = (array) $ready_products;
    }

    public function update_compare_ids_after_login( $user_login, $user ){
		$items = $this->get_compare_items();
		$postTypes = \Bricks\Helpers::get_registered_post_types();

		if( $postTypes ) {
			foreach( $postTypes as $type => $label ) {
				$cookie_key = $this->get_cookie_key( $type );
				if( isset( $_COOKIE[ $cookie_key ] ) && ! empty( $_COOKIE[ $cookie_key ] ) ) {
					$this->save_user_compare_items( $type, $user->ID, $cookie_key, ( $items[$type] ?? [] ) );
				} elseif ( metadata_exists( 'user', $user->ID, $cookie_key ) ) {
					$this->save_user_compare_items( $type, $user->ID, $cookie_key, ( $items[$type] ?? [] ) );
				}
			}
		}
    }

    public static function get_days_cache() {
		$cache_days = 7;

		$life = ( !empty( Plugin::$bu_settings['comp_cookie_life'] ) ) ? Plugin::$bu_settings['comp_cookie_life'] : 'week';

		switch ( $life ) {
			case 'week':
				$cache_days = 7;
				break;
			case 'month':
				$cache_days = 30;
				break;
			case '3months':
				$cache_days = 30*3;
				break;
			case 'year':
				$cache_days = 365;
				break;
		}

		return $cache_days;
	}

	public static function get_compare_counter( $post_type ) {
	    return ! empty( self::$compare_ids[ $post_type ] ) ? count(self::$compare_ids[ $post_type ]) : 0;
    }

	public static function get_cookie_key($post_type = 'post' ){
		self::$cmp_cookie_key = self::COOKIE_KEY . "_{$post_type}_" . ( is_multisite() ? get_current_blog_id() : 0 );
		add_filter( 'litespeed_vary_cookies', function($cookies){
			$cookies[] = self::$cmp_cookie_key;
			
			return $cookies;
		});
		return self::$cmp_cookie_key;
	}

	public static function is_item_in_comparelist( $itemId, $post_type ) {
		return in_array($itemId, self::$compare_ids[ $post_type ]);
	}

	public function init_compare() {
		self::$compare_ids = $this->get_compare_items();
		self::$inited = true;
	}

	public function init_actions() {
		add_action( 'wp_login', [ $this, 'update_compare_ids_after_login' ], 10, 2);
		add_action( 'init', function () {
			if ( ! self::$inited ) {
				$this->init_compare();
			}
		}, 15);
	}

    public static function get_instance() {
        if ( null == self::$instance ) {
            self::$instance = new self();
        }

        return self::$instance;
    }
}