<?php

namespace SureCart\WordPress\Shortcodes;

use SureCartBlocks\Blocks\BuyButton\Block as BuyButtonBlock;
use SureCartCore\ServiceProviders\ServiceProviderInterface;

/**
 * Register shortcodes.
 */
class ShortcodesServiceProvider implements ServiceProviderInterface {
	/**
	 * The service container.
	 *
	 * @var \Pimple\Container $container Service Container.
	 */
	protected $container;

	/**
	 * Register all dependencies in the IoC container.
	 *
	 * @param \Pimple\Container $container Service container.
	 * @return void
	 */
	public function register( $container ) {
		$container['surecart.shortcodes'] = function () {
			return new ShortcodesService();
		};
	}

	/**
	 * Bootstrap the service.
	 *
	 * @param \Pimple\Container $container Service container.
	 * @return void
	 */
	public function bootstrap( $container ) {
		$this->container = $container;
		add_action( 'init', [ $this, 'registerShortcodes' ] );
	}

	/**
	 * Register shortcodes.
	 *
	 * @return void
	 */
	public function registerShortcodes() {
		add_shortcode( 'sc_line_item', '__return_false' );
		add_shortcode( 'sc_form', [ $this, 'formShortcode' ] );
		add_shortcode( 'sc_buy_button', [ $this, 'buyButtonShortcode' ], 10, 2 );

		// buttons.
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_dashboard_button',
			'surecart/customer-dashboard-button',
			[
				'show_icon' => true,
				'type'      => 'primary',
				'size'      => 'medium',
			]
		);

		// dashboard.
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_orders',
			'surecart/customer-orders',
			[ 'title' => '' ]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_invoices',
			'surecart/customer-invoices',
			[ 'title' => '' ]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_billing_details',
			'surecart/customer-billing-details',
			[ 'title' => '' ]
		);

		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_charges',
			'surecart/customer-charges',
			[ 'title' => '' ]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_payment_methods',
			'surecart/customer-payment-methods',
			[ 'title' => '' ]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_subscriptions',
			'surecart/customer-subscriptions',
			[ 'title' => '' ]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_downloads',
			'surecart/customer-downloads',
			[ 'title' => '' ]
		);

		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_wordpress_account',
			'surecart/wordpress-account',
			[
				'title' => '',
			]
		);

		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_dashboard_page',
			'surecart/dashboard-page',
			[
				'name' => '',
			]
		);

		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_dashboard',
			'surecart/customer-dashboard-area',
			[ 'name' => '' ]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_customer_dashboard_tab',
			'surecart/dashboard-tab',
			[
				'icon'  => 'shopping-bag',
				'panel' => '',
				'title' => 'test',
			]
		);

		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_cart_menu_icon',
			'surecart/cart-menu-icon-button',
			[
				'cart_icon'              => 'shopping-bag',
				'cart_menu_always_shown' => true,
			]
		);

		// confirmation.
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_order_confirmation',
			'surecart/order-confirmation',
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_order_confirmation_line_items',
			'surecart/order-confirmation-line-items',
		);

		// product page.
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_list',
			'surecart/product-item-list',
			[
				'ids'                => [],
				'columns'            => 4,
				'sort_enabled'       => true,
				'search_enabled'     => true,
				'pagination_enabled' => true,
				'ajax_pagination'    => true,
				'collection_enabled' => true,
				'type'               => 'all',
				'limit'              => 10,
			]
		);

		// Product collection page.
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_collection',
			'surecart/product-collection',
			[
				'collection_id'      => '', // mandatory.
				'columns'            => 4,
				'sort_enabled'       => true,
				'search_enabled'     => true,
				'pagination_enabled' => true,
				'ajax_pagination'    => true,
				'limit'              => 10,
			]
		);

		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_description',
			'surecart/product-description',
			[
				'id' => null,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_title',
			'surecart/product-title',
			[
				'level' => 1,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_price',
			'surecart/product-price',
			[
				'id' => null,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_price_choices',
			'surecart/product-price-choices',
			[
				'label'      => __( 'Pricing', 'surecart' ),
				'columns'    => 2,
				'show_price' => true,
				'id'         => null,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_media',
			'surecart/product-media',
			[
				'auto_height' => true,
				'id'          => null,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_quantity',
			'surecart/product-quantity',
			[
				'id' => null,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_cart_button',
			'surecart/product-buy-button',
			[
				'add_to_cart' => true,
				'text'        => __( 'Add To Cart', 'surecart' ),
				'width'       => 100,
				'id'          => null,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_variant_choices',
			'surecart/product-variant-choices',
			[
				'id' => null,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_add_to_cart_button',
			'surecart/add-to-cart-button',
			[
				'price_id'    => null,
				'variant_id'  => null,
				'type'        => 'primary',
				'size'        => 'medium',
				'button_text' => __( 'Add To Cart', 'surecart' ),
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_collection_tags',
			'surecart/product-collection-tags',
			[
				'id'    => null,
				'count' => 1,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_custom_amount',
			'surecart/product-selected-price-ad-hoc-amount',
			[
				'label' => __( 'Enter an amount', 'surecart' ),
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_page',
			'surecart/product-page',
			[
				'id' => null,
			]
		);

		// generate shortcodes for all our blocks.
		foreach ( glob( SURECART_PLUGIN_DIR . '/packages/blocks-next/build/blocks/**/block.json' ) as $file ) {
			$metadata = wp_json_file_decode( $file, array( 'associative' => true ) );
			$name     = str_replace( 'surecart/', '', $metadata['name'] );
			$name     = str_replace( '-', '_', sanitize_title_with_dashes( $name ) );

			$old_shortcode_names = [
				'product_title',
				'product_description',
				'product_quantity',
				'product_media',
			];

			if ( in_array( $name, $old_shortcode_names, true ) ) {
				$name = $name . '_new';
			}

			$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
				'sc_' . $name,
				$metadata['name'],
			);
		}

		// Register product review shortcode aliases with friendly names.
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_review_rating_stars',
			'surecart/product-review-average-rating-stars',
			[
				'size'            => '20px',
				'fill_color'      => '',
				'link_to_reviews' => false,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_review_rating_value',
			'surecart/product-review-average-rating-value',
			[
				'link_to_reviews' => false,
				'format'          => 'none',
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_review_total_count',
			'surecart/product-review-total-rating',
			[
				'show_label'            => true,
				'show_for_zero_reviews' => true,
				'link_to_reviews'       => true,
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_review_breakdown',
			'surecart/product-review-breakdown',
			[
				'columns'              => 1,
				'fill_color'           => '',
				'bar_fill_color'       => '',
				'bar_background_color' => '',
			]
		);
		$this->container['surecart.shortcodes']->registerBlockShortcodeByName(
			'sc_product_review_add_button',
			'surecart/product-review-add-button',
			[
				'label'       => __( 'Write a Review', 'surecart' ),
				'button_type' => 'both',
				'icon'        => 'edit-2',
				'className'   => 'is-style-fill',
			]
		);

		/*
		 * Pattern shortcodes.
		 * These are shortcodes that render the content of a pattern file.
		 */
		$this->container['surecart.shortcodes']->registerPatternShortcodeByName(
			'sc_product_review_list',
			'product-review-standard' // Pattern file name without path or extension.
		);
	}

	/**
	 * Dashboard tab shortcode.
	 *
	 * @param  array  $attributes Shortcode attributes.
	 * @param  string $content Shortcode content.
	 * @return string Shortcode output.
	 */
	public function dashboardShortcode( $attributes, $content ) {
		$attributes = shortcode_atts(
			[],
			$attributes,
			'sc_customer_dashboard'
		);

		return '<sc-tab-group style="font-size:16px;font-family:var(--sc-font-sans)" class="wp-block-surecart-customer-dashboard alignwide">' . ( new \SureCartBlocks\Blocks\Dashboard\CustomerDashboard\Block() )->render( $attributes, $content ) . '</sc-tab-group>';
	}

	/**
	 * Form shorcode
	 *
	 * @param  array  $atts Shortcode attributes.
	 * @param  string $content Shortcode content.
	 * @param  string $name Shortcode tag.
	 *
	 * @return string Shortcode output.
	 */
	public function formShortcode( $atts, $content, $name ) {
		$atts = shortcode_atts(
			[
				'id' => null,
			],
			$atts,
			'sc_form'
		);

		if ( ! $atts['id'] ) {
			return;
		}

		$form = \SureCart::forms()->get( $atts['id'] );

		// Validate the post is a published sc_form to prevent private post content disclosure.
		if ( ! is_a( $form, 'WP_Post' ) || 'sc_form' !== $form->post_type || 'publish' !== $form->post_status ) {
			return __( 'This form is not available or has been deleted.', 'surecart' );
		}

		global $load_sc_js;
		$load_sc_js = true;

		global $sc_form_id;
		$sc_form_id = $atts['id'];

		return apply_filters( 'surecart/shortcode/render', do_blocks( $form->post_content ), $atts, $name, $form );
	}

	/**
	 * Buy button shortcode.
	 *
	 * @param array  $atts An array of attributes.
	 * @param string $content Content.
	 *
	 * @return string
	 */
	public function buyButtonShortcode( $atts, $content ) {
		// Remove inner shortcode from buy button label.
		$label = strip_shortcodes( $content );
		$atts  = shortcode_atts(
			[
				'type'  => 'primary',
				'size'  => 'medium',
				'label' => $label,
			],
			$atts,
			'sc_buy_button'
		);

		$atts['line_items'] = (array) $this->getShortcodesAtts(
			'sc_line_item',
			$content,
			[
				'price_id'      => null,
				'quantity'      => 1,
				'ad_hoc_amount' => null,
			]
		);

		foreach ( $atts['line_items'] as $key => $line_item ) {
			$atts['line_items'][ $key ]['id'] = $line_item['price_id'];
		}

		$block = new BuyButtonBlock();

		return $block->render( $atts );
	}

	/**
	 * Get specific shortcode atts from content
	 *
	 * @param string $name Name of shortcode.
	 * @param string $content Page content.
	 * @param array  $defaults Defaults for each.
	 * @return array
	 */
	public function getShortcodesAtts( $name, $content, $defaults = [] ) {
		$items = [];

		// if shortcode exists.
		if (
		preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches )
		&& array_key_exists( 2, $matches )
		&& in_array( $name, $matches[2] )
		) {
			foreach ( (array) $matches[0] as $key => $value ) {
				if ( strpos( $value, $name ) !== false ) {
					$items[] = wp_parse_args(
						shortcode_parse_atts( $matches[3][ $key ] ),
						$defaults
					);
				}
			}
		}

		return $items;
	}

	/**
	 * Convert to block.
	 *
	 * @param string   $name The name.
	 * @param stdClass $block The block.
	 * @param array    $defaults The defaults.
	 * @param array    $atts The atts.
	 * @param string   $content The content.
	 *
	 * @return string
	 */
	protected function convertToBlock( $name, $block, $defaults = [], $atts = [], $content = '' ) {
		return( new $block() )->render(
			shortcode_atts(
				$defaults,
				$atts,
				$name
			),
			$content
		);
	}
}
