<?php

namespace Brandy\BlockSettings\GridResponsiveLayout;

use Brandy\Traits\SingletonTrait;
use Brandy\Interfaces\ExternalBlockSettingsInterface;

class Caller implements ExternalBlockSettingsInterface {
	use SingletonTrait;

	protected $supported_blocks = array( 'core/group', 'core/post-template', 'woocommerce/product-collection' );

	public const DEFAULT_VALUE = array(
		'enabled' => false,
		'tablet'  => array(
			'columnType' => 'manual',
			'value'       => '2',
		),
		'mobile'  => array(
			'columnType' => 'manual',
			'value'       => '1',
		),
	);

	public const DEFAULT_SPANNING_VALUE = array(
		'enabled' => false,
		'tablet'  => array(
			'columnSpan' => 1,
			'rowSpan'    => 1,
		),
		'mobile'  => array(
			'columnSpan' => 1,
			'rowSpan'    => 1,
		),
	);

	/**
	 * Track if frontend styles already enqueued.
	 *
	 * @var bool
	 */
	private $frontend_styles_enqueued = false;

	protected function __construct() {
		add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_settings_scripts' ) );
		add_action( 'enqueue_block_assets', array( $this, 'enqueue_editor_styles' ) );
		add_filter( 'block_type_metadata_settings', array( $this, 'declare_attribute' ), 10, 2 );
		add_filter( 'block_type_metadata_settings', array( $this, 'declare_spanning_attribute' ), 10, 2 );

		foreach ( $this->supported_blocks as $block ) {
			add_filter( 'render_block_' . $block, array( $this, 'add_responsive_grid_layout_attribute' ), 10, 3 );
		}

		add_filter( 'render_block', array( $this, 'add_responsive_spanning_attribute' ), 10, 3 );
	}

	private function is_grid_block( $name ) {
		return in_array( $name, $this->supported_blocks );
	}

	public function declare_attribute( $settings ) {
		if ( ! isset( $settings['name'] ) ) {
			return $settings;
		}

		if ( ! $this->is_grid_block( $settings['name'] ?? '' ) ) {
			return $settings;
		}

		if ( ! empty( $settings['attributes'] ) ) {
			$settings['attributes']['responsiveLayout'] = array(
				'type'    => 'object',
				'default' => self::DEFAULT_VALUE,
			);
		}
		return $settings;
	}

	public function declare_spanning_attribute( $settings ) {
		if ( ! isset( $settings['attributes'] ) ) {
			return $settings;
		}

		if ( ! empty( $settings['attributes'] ) ) {
			$settings['attributes']['responsiveSpanning'] = array(
				'type'    => 'object',
				'default' => self::DEFAULT_SPANNING_VALUE,
			);
		}
		return $settings;
	}

	public function enqueue_settings_scripts() {
		wp_enqueue_script(
			'brandy/grid-responsive-layout-controls',
			BRANDY_TEMPLATE_URL . '/inc/BlockSettings/GridResponsiveLayout/script.js',
			array( 'wp-edit-post' ),
			BRANDY_SCRIPT_VERSION,
			true
		);
		wp_enqueue_script(
			'brandy/spanning-responsive-layout-controls',
			BRANDY_TEMPLATE_URL . '/inc/BlockSettings/GridResponsiveLayout/spanning-controls.js',
			array( 'brandy/grid-responsive-layout-controls' ),
			BRANDY_SCRIPT_VERSION,
			true
		);
	}

	/**
	 * Enqueue styles in editor so responsive grid preview works.
	 */
	public function enqueue_editor_styles() {
		$this->maybe_enqueue_frontend_styles( true );
	}

	/**
	 * Enqueue frontend styles only when needed.
	 */
	private function maybe_enqueue_frontend_styles( $admin_enqueue = false ) {
		if ( ! $admin_enqueue && is_admin() ) {
			return;
		}

		if ( $admin_enqueue && ! is_admin() ) {
			return;
		}

		if ( $this->frontend_styles_enqueued ) {
			return;
		}
		$this->frontend_styles_enqueued = true;
		wp_register_style( 'brandy/grid-responsive-layout-style', false );
		wp_enqueue_style( 'brandy/grid-responsive-layout-style' );
		wp_add_inline_style( 'brandy/grid-responsive-layout-style', $this->get_css() );
	}

	public function get_css() {
		ob_start();
		?>
		@media screen and (min-width:480px) and (max-width:1023px){.is-layout-grid.is-responsive-grid-layout,.is-responsive-grid-layout .wp-block-woocommerce-product-template{grid-template-columns:var(--responsive-grid-layout-tablet-columns)!important}.has-responsive-spanning{grid-column:span var(--responsive-spanning-column-tablet)!important;grid-row:span var(--responsive-spanning-row-tablet)!important}}@media screen and (max-width:479px){.is-layout-grid.is-responsive-grid-layout,.is-responsive-grid-layout .wp-block-woocommerce-product-template{grid-template-columns:var(--responsive-grid-layout-mobile-columns)!important}.has-responsive-spanning{grid-column:span var(--responsive-spanning-column-mobile)!important;grid-row:span var(--responsive-spanning-row-mobile)!important}} .wc-block-product-template:not(.wc-block-product-template__responsive, .embla__container)[class*="columns-"] {display:grid;} .wc-block-product-template:not(.wc-block-product-template__responsive, .embla__container).columns-2{grid-template-columns:repeat(2, 1fr);} .wc-block-product-template:not(.wc-block-product-template__responsive, .embla__container).columns-3{grid-template-columns:repeat(3, 1fr);} .wc-block-product-template:not(.wc-block-product-template__responsive, .embla__container).columns-4{grid-template-columns:repeat(4, 1fr);} .wc-block-product-template:not(.wc-block-product-template__responsive, .embla__container).columns-5{grid-template-columns:repeat(5, 1fr);} .wc-block-template:not(.wc-block-product-template__responsive, .embla__container).columns-6 {grid-template-columns:repeat(6,1fr);} .wc-block-product-template:not(.wc-block-product-template__responsive, .embla__container)[class*="columns-"].is-flex-container.is-flex-container>li {width: 100%;}
		<?php
		return ob_get_clean();
	}

	public function add_responsive_grid_layout_attribute( $block_content, $block, $instance ) {
		if ( empty( $block['attrs'] ) ) {
			return $block_content;
		}

		$attributes = (array) $block['attrs'];

		if ( empty( $attributes ) ) {
			return $block_content;
		}

		if ( ! isset( $attributes['layout']['type'] ) && ! isset( $attributes['displayLayout']['type'] ) ) {
			return $block_content;
		}

		if ( isset( $attributes['layout']['type'] ) && 'grid' !== $attributes['layout']['type'] ) {
			return $block_content;
		}

		if ( isset( $attributes['displayLayout']['type'] ) && 'flex' !== $attributes['displayLayout']['type'] ) {
			return $block_content;
		}

		$responsive_layout_settings = $attributes['responsiveLayout'] ?? self::DEFAULT_VALUE;

		if ( $responsive_layout_settings['enabled'] ) {
			$this->maybe_enqueue_frontend_styles();

			$class = 'is-responsive-grid-layout';
			$tags  = new \WP_HTML_Tag_Processor( $block_content );

			if ( $tags->next_tag() ) {
				$existing_class = $tags->get_attribute( 'class' ) ?? '';
				$tags->set_attribute( 'class', $existing_class . ' ' . $class );

				$escape_styles = array();

				foreach ( array( 'tablet', 'mobile' ) as $device ) {
					$columnType   = $responsive_layout_settings[ $device ]['columnType'] ?? self::DEFAULT_VALUE[ $device ]['columnType'];
					$column_value = $responsive_layout_settings[ $device ]['value'] ?? self::DEFAULT_VALUE[ $device ]['value'];

					if ( 'manual' === $columnType ) {
						$column_value = absint( $column_value );
						$escape_styles[] = '--responsive-grid-layout-' . $device . '-columns:repeat(' . $column_value . ', 1fr)';
					} else {
						$column_value = esc_attr( $column_value );
						$escape_styles[] = '--responsive-grid-layout-' . $device . '-columns:repeat(auto-fill, minmax(min(' . $column_value . ', 100%), 1fr))';
					}
				}

				$existing_style = $tags->get_attribute( 'style' );

				if ( empty( $existing_style ) ) {
					$existing_style = '';
				} elseif ( ! str_ends_with( $existing_style, ';' ) ) {
					$existing_style .= ';';
				}

				$updated_style  = $existing_style;
				$updated_style .= implode( ';', $escape_styles );
				$tags->set_attribute( 'style', $updated_style );

				$block_content = $tags->get_updated_html();
			}
		}

		return $block_content;
	}

	public function add_responsive_spanning_attribute( $block_content, $block, $instance ) {
		if ( empty( $block['attrs'] ) ) {
			return $block_content;
		}

		$attributes = (array) $block['attrs'];

		if ( empty( $block['parentLayout']['type'] ) || 'grid' !== $block['parentLayout']['type'] ) {
			return $block_content;
		}

		$responsive_spanning_settings = $attributes['responsiveSpanning'] ?? self::DEFAULT_SPANNING_VALUE;

		if ( $responsive_spanning_settings['enabled'] ) {
			$this->maybe_enqueue_frontend_styles();

			$class = 'has-responsive-spanning';
			$tags  = new \WP_HTML_Tag_Processor( $block_content );

			if ( $tags->next_tag() ) {
				$existing_class = $tags->get_attribute( 'class' ) ?? '';
				$tags->set_attribute( 'class', $existing_class . ' ' . $class );

				$escape_styles = array();

				foreach ( array( 'tablet', 'mobile' ) as $device ) {
					$columnSpan = absint( $responsive_spanning_settings[ $device ]['columnSpan'] );
					$rowSpan    = absint( $responsive_spanning_settings[ $device ]['rowSpan'] );

					$escape_styles[] = '--responsive-spanning-column-' . $device . ':' . $columnSpan;
					$escape_styles[] = '--responsive-spanning-row-' . $device . ':' . $rowSpan;
				}

				$existing_style = $tags->get_attribute( 'style' );

				if ( empty( $existing_style ) ) {
					$existing_style = '';
				} elseif ( ! str_ends_with( $existing_style, ';' ) ) {
					$existing_style .= ';';
				}

				$updated_style  = $existing_style;
				$updated_style .= implode( ';', $escape_styles );
				$tags->set_attribute( 'style', $updated_style );

				$block_content = $tags->get_updated_html();
			}
		}

		return $block_content;
	}
}

Caller::get_instance();
