<?php

namespace ElementPack\Includes\Builder;

if ( ! defined( 'WPINC' ) ) {
	die;
}

use Elementor\Plugin;
use Elementor\Controls_Manager;
use Elementor\Core\DocumentTypes\PageBase;
use ElementPack\Base\Singleton;
use ElementPack\Includes\Builder\Meta;
use ElementPack\Includes\Builder\Builder_Template_Helper;
use ElementPack\Includes\Builder\Builder_Post_Singleton;
use ElementPack\Includes\Builder\Template_Conditions;
use ElementPack\Includes\Builder\Theme_Builder_Admin;
use ElementPack\Includes\Controls\SelectInput\Dynamic_Select;


class Builder_Integration {

	use Singleton;

	private $current_template = null;

	/**
	 * When template preview params are validated, reuse this template ID for the rest of the request.
	 *
	 * @var int|null
	 */
	private $preview_locked_template_id = null;

	public $current_template_id = null;

	function __construct() {
		add_filter( 'template_include', [ $this, 'set_builder_template' ], 9999 );
		add_action( 'elementor/editor/init', [ $this, 'set_sample_post' ], 999 );
		add_action( 'elementor/editor/after_enqueue_scripts', [ $this, 'enqueue_editor_theme_builder_flow' ], 30 );

		add_action( 'print_default_editor_scripts', array( $this, 'my_custom_fonts' ) );
		add_filter( 'elementor/document/urls/wp_preview', [ $this, 'change_preview_editor_url' ], 999, 2 );

		add_action( 'elementor/documents/register_controls', [ $this, 'register_document_controls' ] );

		// Demo bypass: preview_nonce === 'verified' on front (see filter_preview_verified_bypass).
		add_filter( 'element_pack/preview/verified_bypass', [ $this, 'filter_preview_verified_bypass' ], 10, 1 );

		// When true, preview URL uses nonce "verified" instead of wp_create_nonce (see Ultimate Store Kit).
		add_filter( 'element_pack/preview/use_demo_bypass', [ $this, 'filter_preview_use_demo_bypass' ], 10, 1 );

		// Woo Launch Your Store: coming soon replaces template_include and exits() before our handler runs — exclude TB preview URLs.
		add_filter( 'woocommerce_coming_soon_exclude', [ $this, 'woocommerce_exclude_coming_soon_for_builder_preview' ], 5 );
	}

	/**
	 * Allow preview_nonce === 'verified' on demo hosts, common local TLDs, and WP environment type.
	 * USK only checks strpos() against a short host list — *.local (Local WP, etc.) never matches "localhost".
	 *
	 * @param mixed $verify Previous value (Ultimate Store Kit passes bool).
	 * @return bool
	 */
	public function filter_preview_verified_bypass( $verify ) {
		if ( $verify ) {
			return true;
		}

		if ( apply_filters( 'element_pack/preview/allow_verified_bypass', false ) ) {
			return true;
		}

		// Honour Ultimate Store Kit if both plugins active (shared demo stacks).
		if ( apply_filters( 'ultimate_store_kit/preview/verified_bypass', false ) ) {
			return true;
		}

		$request_host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated

		if ( '' === $request_host ) {
			return false;
		}

		$host_lc = strtolower( preg_replace( '/:\d+$/', '', $request_host ) );

		if ( function_exists( 'wp_get_environment_type' ) ) {
			$env = wp_get_environment_type();
			if ( in_array( $env, array( 'local', 'development' ), true ) ) {
				return true;
			}
		}

		foreach ( array( '.local', '.test', '.invalid', '.localhost', '.docker.internal', '.ddev.site', '.wpsandbox.net' ) as $suffix ) {
			if ( strlen( $host_lc ) > strlen( $suffix ) && substr( $host_lc, -strlen( $suffix ) ) === $suffix ) {
				return true;
			}
		}

		if ( 'localhost' === $host_lc || '127.0.0.1' === $host_lc || false !== strpos( $host_lc, '::1' ) ) {
			return true;
		}

		// Typical LAN IPs (preview from another device via http://192.168.x.x/... ).
		if ( preg_match( '/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $host_lc, $m ) ) {
			$o = array_map( 'intval', array_slice( $m, 1, 4 ) );
			if ( count( $o ) === 4 && $o[0] <= 255 && $o[1] <= 255 && $o[2] <= 255 && $o[3] <= 255 ) {
				if ( 192 === $o[0] && 168 === $o[1] ) {
					return true;
				}
				if ( 10 === $o[0] ) {
					return true;
				}
				if ( 172 === $o[0] && $o[1] >= 16 && $o[1] <= 31 ) {
					return true;
				}
			}
		}

		$demo_hosts = apply_filters(
			'element_pack/preview/demo_hosts',
			array(
				'elementpack.pro',
				'section.predesignkit.com',
				'templates.elementpack.pro/ecommerce',
				'bdthemes.com',
				'localhost',
				'127.0.0.1',
			)
		);

		foreach ( (array) $demo_hosts as $host ) {
			$needle = strtolower( trim( (string) $host ) );
			if ( '' !== $needle && false !== strpos( $host_lc, $needle ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Mirrors {@see Builder_Integration::filter_preview_verified_bypass()} for URL generation in the editor.
	 * USK only checks ?action=elementor; we also allow local/development so verified URLs are generated when env matches.
	 *
	 * @param mixed $use_demo Previous value.
	 * @return bool
	 */
	public function filter_preview_use_demo_bypass( $use_demo ) {
		if ( $use_demo ) {
			return true;
		}

		if ( apply_filters( 'element_pack/preview/force_demo_bypass', false ) ) {
			return true;
		}

		if ( apply_filters( 'ultimate_store_kit/preview/use_demo_bypass', false ) ) {
			return true;
		}

		if ( function_exists( 'wp_get_environment_type' ) && in_array( wp_get_environment_type(), array( 'local', 'development' ), true ) ) {
			return true;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		return isset( $_GET['action'] ) && 'elementor' === sanitize_text_field( wp_unslash( $_GET['action'] ) );
	}

	/**
	 * Exclude Theme Builder preview from WooCommerce "Launch your store" coming soon (loads before our template_include).
	 *
	 * @since WC 9.1.0 Filter: woocommerce_coming_soon_exclude
	 *
	 * @param bool $excluded Passed through.
	 * @return bool
	 */
	public function woocommerce_exclude_coming_soon_for_builder_preview( $excluded ) {
		if ( $excluded ) {
			return true;
		}

		return $this->is_theme_builder_frontend_preview_request();
	}

	/**
	 * Whether the current HTTP request is our Theme Builder preview URL (strict enough to avoid blank coming-soon bypass).
	 *
	 * @return bool
	 */
	public function is_theme_builder_frontend_preview_request() {
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		if ( empty( $_GET['preview'] ) || ! isset( $_GET['bdt_template_id'], $_GET['preview_nonce'] ) ) {
			return false;
		}

		$template_post_id = absint( wp_unslash( $_GET['bdt_template_id'] ) );
		if ( $template_post_id < 1 ) {
			return false;
		}

		if ( Meta::POST_TYPE !== get_post_type( $template_post_id ) ) {
			return false;
		}

		$nonce_raw = sanitize_text_field( wp_unslash( $_GET['preview_nonce'] ) );
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		return '' !== trim( $nonce_raw );
	}

	/**
	 * Frontend preview URL + query args (`bdt_template_id`, `preview_nonce`, `preview`).
	 *
	 * @param string                               $url      Default preview URL.
	 * @param \Elementor\Core\Base\Document|object $document Current document.
	 * @return string
	 */
	public function change_preview_editor_url( $url, $document ) {
		if ( ! is_object( $document ) || ! method_exists( $document, 'get_main_id' ) ) {
			return $url;
		}

		$post_id = (int) $document->get_main_id();
		if ( $post_id < 1 || Meta::POST_TYPE !== get_post_type( $post_id ) ) {
			return $url;
		}

		$template_type = get_post_meta( $post_id, Meta::TEMPLATE_TYPE, true );
		if ( empty( $template_type ) ) {
			return $url;
		}

		$sep = Builder_Template_Helper::separator();
		$parts = explode( $sep, $template_type );
		if ( count( $parts ) < 2 ) {
			return $url;
		}

		$post_type_key = $parts[0];
		$slug          = $parts[1];

		$template_url = $this->resolve_builder_preview_target_url( $post_id, $post_type_key, $slug );
		if ( empty( $template_url ) ) {
			return $url;
		}

		$is_demo  = apply_filters( 'element_pack/preview/use_demo_bypass', false );
		$nonce_in = $is_demo ? 'verified' : wp_create_nonce( 'template_preview_' . $post_id );

		return add_query_arg(
			array(
				'bdt_template_id' => $post_id,
				'preview_nonce'   => $nonce_in,
				'preview'         => true,
			),
			$template_url
		);
	}

	/**
	 * Real URL for Theme Builder preview from meta `post_type|slug`.
	 *
	 * @param int    $builder_post_id Builder post ID.
	 * @param string $post_type_key   Meta first segment (e.g. post, page, product).
	 * @param string $slug            Meta second segment (e.g. single, shop).
	 * @return string
	 */
	protected function resolve_builder_preview_target_url( $builder_post_id, $post_type_key, $slug ) {
		switch ( $post_type_key ) {

			case 'themes':
				if ( 'header' === $slug || 'footer' === $slug ) {
					return home_url( '/' );
				}
				break;

			case 'post':
				return $this->resolve_post_builder_preview_url( $builder_post_id, $slug );

			case 'page':
				return $this->resolve_page_builder_preview_url( $builder_post_id, $slug );

			case 'product':
				if ( class_exists( 'WooCommerce' ) ) {
					return $this->resolve_product_builder_preview_url( $builder_post_id, $slug );
				}
				break;

			default:
				return $this->resolve_custom_post_builder_preview_url( $builder_post_id, $post_type_key, $slug );
		}

		return '';
	}

	/**
	 * @param int    $builder_post_id Builder ID.
	 * @param string $slug            Archive / single slug.
	 * @return string
	 */
	protected function resolve_post_builder_preview_url( $builder_post_id, $slug ) {
		switch ( $slug ) {
			case 'single':
				$sample_id = $this->get_document_sample_post_id( $builder_post_id );
				if ( $sample_id ) {
					return get_permalink( $sample_id );
				}
				$posts = get_posts(
					array(
						'post_type'      => 'post',
						'post_status'    => 'publish',
						'posts_per_page' => 1,
						'fields'         => 'ids',
					)
				);

				return ! empty( $posts ) ? get_permalink( $posts[0] ) : get_post_type_archive_link( 'post' );

			case 'archive':
				return get_post_type_archive_link( 'post' ) ?: home_url( '/' );

			case 'category':
				$terms = get_terms(
					array(
						'taxonomy'   => 'category',
						'hide_empty' => true,
						'number'     => 1,
					)
				);

				return ( ! empty( $terms ) && ! is_wp_error( $terms ) ) ? get_term_link( $terms[0] ) : '';

			case 'tag':
				$terms = get_terms(
					array(
						'taxonomy'   => 'post_tag',
						'hide_empty' => true,
						'number'     => 1,
					)
				);

				return ( ! empty( $terms ) && ! is_wp_error( $terms ) ) ? get_term_link( $terms[0] ) : '';

			case 'author':
				$authors = get_users(
					array(
						'number'     => 1,
						'orderby'    => 'post_count',
						'order'      => 'DESC',
						'capability' => 'edit_posts',
					)
				);

				return ! empty( $authors ) ? get_author_posts_url( $authors[0]->ID ) : '';

			case 'date':
				return home_url( '/' );
		}

		return '';
	}

	/**
	 * @param int    $builder_post_id Builder ID.
	 * @param string $slug            Page template slug (single, 404, search).
	 * @return string
	 */
	protected function resolve_page_builder_preview_url( $builder_post_id, $slug ) {
		switch ( $slug ) {
			case 'single':
				$sample_id = $this->get_document_sample_post_id( $builder_post_id );
				if ( $sample_id ) {
					return get_permalink( $sample_id );
				}
				$pages = get_posts(
					array(
						'post_type'      => 'page',
						'post_status'    => 'publish',
						'posts_per_page' => 1,
						'fields'         => 'ids',
					)
				);

				return ! empty( $pages ) ? get_permalink( $pages[0] ) : home_url( '/' );

			case '404':
				return home_url( '/__element_pack_builder_preview_404_' . wp_rand( 10000, 99999 ) . '/' );

			case 'search':
				return home_url( '/?s=' . rawurlencode( 'elementor' ) );
		}

		return '';
	}

	/**
	 * @param int    $builder_post_id Builder ID.
	 * @param string $slug            Woo slug (shop, cart, …).
	 * @return string
	 */
	protected function resolve_product_builder_preview_url( $builder_post_id, $slug ) {
		switch ( $slug ) {
			case 'category':
				$cats = get_terms(
					array(
						'taxonomy'   => 'product_cat',
						'hide_empty' => true,
						'number'     => 1,
					)
				);

				return ( ! empty( $cats ) && ! is_wp_error( $cats ) ) ? get_term_link( $cats[0] ) : '';

			case 'tag':
				$tags = get_terms(
					array(
						'taxonomy'   => 'product_tag',
						'hide_empty' => true,
						'number'     => 1,
					)
				);

				return ( ! empty( $tags ) && ! is_wp_error( $tags ) ) ? get_term_link( $tags[0] ) : '';

			case 'shop':
			case 'archive':
				$shop_id = function_exists( 'wc_get_page_id' ) ? wc_get_page_id( 'shop' ) : 0;

				return $shop_id ? get_permalink( $shop_id ) : get_post_type_archive_link( 'product' );

			case 'single':
				$sample_product = $this->get_document_sample_post_id( $builder_post_id );

				return $sample_product ? get_permalink( $sample_product ) : $this->get_default_product_permalink();

			case 'cart':
				return function_exists( 'wc_get_cart_url' ) ? wc_get_cart_url() : '';

			case 'checkout':
				return function_exists( 'wc_get_checkout_url' ) ? wc_get_checkout_url() : '';

			case 'thankyou':
				if ( function_exists( 'wc_get_orders' ) && function_exists( 'wc_get_checkout_url' ) ) {
					$orders = wc_get_orders( array( 'limit' => 1 ) );
					if ( ! empty( $orders ) && is_object( $orders[0] ) && method_exists( $orders[0], 'get_id' ) ) {
						return add_query_arg( 'order-received', $orders[0]->get_id(), wc_get_checkout_url() );
					}
				}
				break;

			case 'orders':
				if ( function_exists( 'wc_get_endpoint_url' ) && function_exists( 'wc_get_page_permalink' ) ) {
					return wc_get_endpoint_url( 'orders', '', wc_get_page_permalink( 'myaccount' ) );
				}
				break;

			case 'myaccount':
				return function_exists( 'wc_get_page_id' )
					? get_permalink( wc_get_page_id( 'myaccount' ) )
					: '';
		}

		return '';
	}

	/**
	 * Custom post type / taxonomy templates.
	 *
	 * @param int    $builder_post_id Builder ID.
	 * @param string $post_type       CPT slug from meta.
	 * @param string $slug            Location slug.
	 * @return string
	 */
	protected function resolve_custom_post_builder_preview_url( $builder_post_id, $post_type, $slug ) {
		$taxonomies = get_object_taxonomies( $post_type, 'objects' );

		foreach ( $taxonomies as $tax ) {
			if ( $tax->public && $tax->show_ui && $slug === $tax->name ) {
				$terms = get_terms(
					array(
						'taxonomy'   => $tax->name,
						'hide_empty' => true,
						'number'     => 1,
					)
				);

				return ( ! empty( $terms ) && ! is_wp_error( $terms ) ) ? get_term_link( $terms[0] ) : '';
			}
		}

		switch ( $slug ) {
			case 'single':
				$sample = $this->get_document_sample_post_id( $builder_post_id );

				return $sample ? get_permalink( $sample ) : $this->get_first_public_post_link( $post_type );

			case 'archive':
				return get_post_type_archive_link( $post_type ) ?: home_url( '/' );
		}

		return '';
	}

	/**
	 * Elementor document “Builder Post” sample ID.
	 *
	 * @param int $document_post_id bdt-template-builder post ID.
	 * @return int
	 */
	protected function get_document_sample_post_id( $document_post_id ) {
		try {
			$page_settings_manager = \Elementor\Core\Settings\Manager::get_settings_managers( 'page' );
			if ( ! $page_settings_manager ) {
				return 0;
			}
			$page_settings_model = $page_settings_manager->get_model( $document_post_id );

			return (int) ( method_exists( $page_settings_model, 'get_settings' )
				? $page_settings_model->get_settings( 'bdt_builder_sample_post_id' )
				: 0 );
		} catch ( \Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
			return 0;
		}
	}

	/**
	 * @param string $post_type CPT slug.
	 * @return string
	 */
	protected function get_first_public_post_link( $post_type ) {
		$ids = get_posts(
			array(
				'post_type'      => $post_type,
				'post_status'    => 'publish',
				'posts_per_page' => 1,
				'fields'         => 'ids',
			)
		);

		return ! empty( $ids ) ? get_permalink( $ids[0] ) : '';
	}

	/**
	 * @return string
	 */
	protected function get_default_product_permalink() {
		if ( function_exists( 'wc_get_products' ) ) {
			$products = wc_get_products(
				array(
					'status' => 'publish',
					'limit'  => 1,
				)
			);
			if ( ! empty( $products ) && isset( $products[0] ) && is_object( $products[0] ) && method_exists( $products[0], 'get_id' ) ) {
				return get_permalink( $products[0]->get_id() );
			}
		}

		return function_exists( 'wc_get_page_id' ) ? get_permalink( wc_get_page_id( 'shop' ) ) : home_url( '/' );
	}

	public function my_custom_fonts() {
		if ( is_admin() && Plugin::instance()->editor->is_edit_mode() ) {
			if ( isset( $_REQUEST['bdt-template'] ) ) {
				wp_register_style( 'bdt-template-builder-hide-preview-btn-inline', false ); // phpcs:ignore
				wp_enqueue_style( 'bdt-template-builder-hide-preview-btn-inline' );
				wp_add_inline_style(
					'bdt-template-builder-hide-preview-btn-inline',
					'#elementor-panel-footer-saver-preview {display:none!important}'
				);
			}
		}
	}
	function set_sample_post() {
		if ( Builder_Template_Helper::isTemplateEditMode() ) {
			$object = Builder_Post_Singleton::instance();
			$object::set_sample_post();
		}
	}

	public function enqueue_editor_theme_builder_flow() {
		if ( ! is_admin() || ! Plugin::instance()->editor->is_edit_mode() ) {
			return;
		}

		// IMPORTANT: don't rely on Builder_Template_Helper::isTemplateEditMode()
		// here — by the time `elementor/editor/after_enqueue_scripts` fires,
		// `set_sample_post()` (hooked on `elementor/editor/init`) has already
		// swapped $GLOBALS['post'] with a sample post (e.g. a real WP post for
		// "post|single", a product for "product|single", etc.) for every type
		// except themes|header / themes|footer (no posts of post_type "themes"
		// exist, so the swap never happens). That swap makes `get_post_type()`
		// return 'post' / 'page' / 'product' instead of bdt-template-builder
		// and the helper bails out. Instead resolve the template post directly
		// from the URL, which is unaffected by the swap.
		$post_id = 0;
		if ( isset( $_REQUEST['post'] ) ) {
			$post_id = absint( $_REQUEST['post'] );
		}
		if ( ! $post_id ) {
			global $post;
			$post_id = isset( $post->ID ) ? (int) $post->ID : 0;
		}
		if ( ! $post_id || get_post_type( $post_id ) !== Meta::POST_TYPE ) {
			return;
		}

		$template_type = (string) get_post_meta( $post_id, Meta::TEMPLATE_TYPE, true );
		$rows          = Template_Conditions::get_rows( $post_id );

		$assets_dir = defined( 'BDTEP_ADMIN_PATH' ) ? constant( 'BDTEP_ADMIN_PATH' ) . 'assets/' : '';

		$script_name = 'js/ep-tb-editor-flow.min.js';
		$script_url  = BDTEP_ADMIN_ASSETS_URL . $script_name;
		$script_path = $assets_dir ? $assets_dir . $script_name : '';
		$script_ver  = ( $script_path && file_exists( $script_path ) ) ? (string) filemtime( $script_path ) : BDTEP_VER;

		$style_name = 'css/ep-tb-editor-flow.css';
		$style_url  = BDTEP_ADMIN_ASSETS_URL . $style_name;
		$style_path = $assets_dir ? $assets_dir . $style_name : '';
		$style_ver  = ( $style_path && file_exists( $style_path ) ) ? (string) filemtime( $style_path ) : BDTEP_VER;

		wp_enqueue_style( 'bdt-tb-editor-flow', $style_url, [], $style_ver );

		$script_deps = [ 'jquery', 'element-pack' ];
		if ( wp_script_is( 'elementor-v2-editor-app-bar', 'registered' ) ) {
			$script_deps[] = 'elementor-v2-editor-app-bar';
		}
		if ( wp_script_is( 'elementor-select2', 'registered' ) || wp_script_is( 'elementor-select2', 'enqueued' ) ) {
			$script_deps[] = 'elementor-select2';
		}
		wp_enqueue_script( 'bdt-tb-editor-flow', $script_url, $script_deps, $script_ver, true );

		$ep_logo_url = BDTEP_ASSETS_URL . 'images/logo.svg';
		$ep_logo_path = BDTEP_ASSETS_PATH . 'images/logo.svg';
		$ep_logo_ver   = is_readable( $ep_logo_path ) ? (string) filemtime( $ep_logo_path ) : BDTEP_VER;

		wp_localize_script(
			'bdt-tb-editor-flow',
			'bdtTbEditorFlow',
			[
				'postId'          => $post_id,
				'templateType'    => $template_type,
				'libraryDefaultTab' => $this->get_elementpack_library_default_tab( $template_type ),
				'templateLabel'   => $template_type ? Builder_Template_Helper::getTemplateByIndex( $template_type ) : '',
				'conditions'      => $rows,
				'pluginLogoUrl'   => esc_url_raw( add_query_arg( 'ver', $ep_logo_ver, $ep_logo_url ) ),
				'ajaxurl'         => admin_url( 'admin-ajax.php' ),
				'nonce'           => wp_create_nonce( 'element_pack_builder_nonce' ),
				'restSingular'    => rest_url( 'bdt/v1/get-singular-list' ),
				'restTerms'       => rest_url( 'bdt/v1/get-term-list' ),
				'restUsers'       => rest_url( 'bdt/v1/get-user-list' ),
				'restNonce'       => wp_create_nonce( 'wp_rest' ),
				'locationOptions' => Theme_Builder_Admin::get_location_options(),
				'singularOptions' => Theme_Builder_Admin::get_singular_suboptions(),
				'archiveOptions'  => Theme_Builder_Admin::get_archive_suboptions(),
				'wooOptions'      => Theme_Builder_Admin::get_woo_suboptions(),
				'strings'         => [
					'conditionsTitle' => __( 'Where do you want to display your template?', 'bdthemes-element-pack' ),
					'conditionsDesc'  => __( 'Set the conditions that determine where your template is used throughout your site. For example, choose Entire Site to display the template across your site.', 'bdthemes-element-pack' ),
					'displayConditions' => __( 'Display Conditions', 'bdthemes-element-pack' ),
					'publishSettings'   => __( 'Publish Settings', 'bdthemes-element-pack' ),
					'modalClose'       => __( 'Close', 'bdthemes-element-pack' ),
					'include'         => __( 'Include', 'bdthemes-element-pack' ),
					'exclude'         => __( 'Exclude', 'bdthemes-element-pack' ),
					'addCondition'    => __( 'Add Condition', 'bdthemes-element-pack' ),
					'removeCondition' => __( 'Remove condition', 'bdthemes-element-pack' ),
					'saveClose'       => __( 'Save & Close', 'bdthemes-element-pack' ),
					'cancel'          => __( 'Cancel', 'bdthemes-element-pack' ),
					'saving'          => __( 'Saving…', 'bdthemes-element-pack' ),
					'saveFailed'      => __( 'Failed to save conditions.', 'bdthemes-element-pack' ),
					'idsPlaceholder'  => __( 'Select…', 'bdthemes-element-pack' ),
					/* Translators: optional refinement search next to Singular › Posts/Pages (Elementor-style). */
					'conditionRefinePlaceholder' => __( 'Search', 'bdthemes-element-pack' ),
				],
			]
		);
	}

	/**
	 * Element Pack Template Library tab (Headers / Footers radio) for Theme Builder part types.
	 *
	 * @param string $template_type Meta index e.g. themes|header.
	 * @return string Tab key (bdt_elementpack_header, …) or empty to keep global default.
	 */
	private function get_elementpack_library_default_tab( $template_type ) {
		$template_type = (string) $template_type;
		if ( '' === $template_type ) {
			return '';
		}
		$sep = Builder_Template_Helper::separator();
		if ( 'themes' . $sep . 'header' === $template_type ) {
			return 'bdt_elementpack_header';
		}
		if ( 'themes' . $sep . 'footer' === $template_type ) {
			return 'bdt_elementpack_footer';
		}
		return '';
	}

	function register_document_controls( $document ) {
		if ( ! $document instanceof PageBase || ! $document::get_property( 'has_elements' ) ) {
			return;
		}

		if ( Plugin::instance()->preview->is_preview_mode() )
			return;

		if ( ! Builder_Template_Helper::isTemplateEditMode() ) {
			return;
		}

		global $post;

		if ( ! isset( $post->ID ) ) {
			return;
		}
		$meta = get_post_meta( $post->ID );

		$templateMeta = optional( $meta )[ Meta::TEMPLATE_TYPE ];
		if ( ! isset( $templateMeta[0] ) ) {
			return;
		}
		$postMeta = $templateMeta[0];
		$postMeta = explode( '|', $postMeta );
		$postType = $postMeta[0];

		if ( 'single' != $postMeta[1] ) {
			return;
		}

		$document->start_controls_section(
			'bdt_page_setting_preview',
			[ 
				'label' => esc_html__( 'Builder Settings', 'bdthemes-element-pack' ),
				'tab'   => Controls_Manager::TAB_SETTINGS,
			]
		);

		$document->add_control(
			'bdt_builder_sample_post_id',
			[ 
				'label'       => esc_html__( 'Builder Post', 'bdthemes-element-pack' ),
				'type'        => Dynamic_Select::TYPE,
				'multiple'    => false,
				'label_block' => true,
				'query_args'  => [ 
					'post_type' => $postType
				],
			]
		);

		$document->add_control(
			'bdt_builder_sample_apply_preview',
			[ 
				'type'        => Controls_Manager::BUTTON,
				'label'       => esc_html__( 'Apply & Preview', 'bdthemes-element-pack' ),
				'label_block' => true,
				'show_label'  => false,
				'text'        => esc_html__( 'Apply & Preview', 'bdthemes-element-pack' ),
				'separator'   => 'none',
				'event'       => 'ElementPackBuilderSetting:applySinglePagePostOnPreview',
			]
		);

		$document->end_controls_section();
	}

	/**
	 * Rewrite default template
	 *
	 */
	function set_builder_template( $template ) {
		if ( Builder_Template_Helper::isTemplateEditMode() ) {
			return $this->setBackendTemplate( $template );
		} else {
			return $this->setFrontendTemplate( $template );
		}
	}


	protected function setBackendTemplate( $template ) {
		return $template;
	}

	/**
	 * Cart, Checkout, My Account, and the Shop archive are WP Pages (`post_type` = page).
	 * If we resolve {@see page|single} Theme Builder templates first, we never reach the
	 * WooCommerce `product|cart`, `product|checkout`, etc. branch — so storefront TB templates
	 * never load on the frontend.
	 */
	protected function is_woocommerce_primary_storefront_page_request() {
		if ( ! class_exists( 'WooCommerce' ) ) {
			return false;
		}

		if ( function_exists( 'is_cart' ) && is_cart() ) {
			return true;
		}

		if ( function_exists( 'is_checkout' ) && is_checkout() ) {
			return true;
		}

		if ( function_exists( 'is_account_page' ) && is_account_page() ) {
			return true;
		}

		if ( function_exists( 'is_shop' ) && is_shop() ) {
			return true;
		}

		return false;
	}

	/**
	 * Whether the current request is a blog post archive (not search, WooCommerce, or CPT archives).
	 */
	protected function is_post_blog_archive_request() {
		if ( is_search() ) {
			return false;
		}

		if ( class_exists( 'WooCommerce' ) ) {
			if ( ( function_exists( 'is_shop' ) && is_shop() )
				|| ( function_exists( 'is_product_taxonomy' ) && is_product_taxonomy() )
				|| is_post_type_archive( 'product' ) ) {
				return false;
			}
		}

		if ( is_category() || is_tag() || is_author() || is_date() ) {
			return true;
		}

		if ( is_home() ) {
			return true;
		}

		if ( is_post_type_archive( 'post' ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Resolve post archive shell path for the current request.
	 *
	 * @return string Relative path under templates/posts/ without .php.
	 */
	protected function get_post_archive_shell_slug() {
		if ( is_category() ) {
			return 'posts/category';
		}
		if ( is_tag() ) {
			return 'posts/tag';
		}
		if ( is_author() ) {
			return 'posts/author';
		}
		if ( is_date() ) {
			return 'posts/date';
		}

		return 'posts/archive';
	}


	protected function setFrontendTemplate( $template ) {
		// if (get_post_type() == 'product') {
		//     global $product;
		//     $product = wc_get_product();
		// }



		if ( defined( 'ELEMENTOR_PATH' ) ) {
			$elementorTem = ELEMENTOR_PATH . "modules/page-templates/templates/";
			$elementorTem = explode( $elementorTem, $template );
			if ( count( $elementorTem ) == 2 ) {
				return $template;
			}
		}

		// single posts
		if ( is_single() && 'post' == get_post_type() ) {
			//single__3168
			if ( $custom_template = $this->get_template_id( 'single', 'post' ) ) {
				$this->current_template_id = $custom_template;
				return $this->getTemplatePath( 'posts/single', $template );
			}
		}

		// Post archives — consolidated post|archive templates + display conditions (Elementor Pro style).
		if ( $this->is_post_blog_archive_request() ) {
			$sep            = Builder_Template_Helper::separator();
			$legacy_types   = [
				'post' . $sep . 'category',
				'post' . $sep . 'tag',
				'post' . $sep . 'author',
				'post' . $sep . 'date',
			];
			$custom_template = Builder_Template_Helper::resolve_template_for_request( 'post' . $sep . 'archive', $legacy_types );

			if ( ! $custom_template ) {
				if ( is_category() ) {
					$custom_template = $this->get_template_id( 'category', 'post' );
				} elseif ( is_tag() ) {
					$custom_template = $this->get_template_id( 'tag', 'post' );
				} elseif ( is_author() ) {
					$custom_template = $this->get_template_id( 'author', 'post' );
				} elseif ( is_date() ) {
					$custom_template = $this->get_template_id( 'date', 'post' );
				} else {
					$custom_template = $this->get_template_id( 'archive', 'post' );
				}
			}

			if ( $custom_template ) {
				$this->current_template_id = $custom_template;
				return $this->getTemplatePath( $this->get_post_archive_shell_slug(), $template );
			}
		}

		// Pages (not WC Cart / Checkout / Account / Shop — those use Theme Builder › product|*)
		if (
			is_page()
			&& ! is_page_template()
			&& 'page' == get_post_type()
			&& ! $this->is_woocommerce_primary_storefront_page_request()
		) {
			if ( $custom_template = $this->get_template_id( 'single', 'page' ) ) {
				$this->current_template_id = $custom_template;
				return $this->getTemplatePath( 'pages/single', $template );
			}
		}

		//  404 page
		if ( is_404() ) {
			if ( $custom_template = $this->get_template_id( '404', 'page' ) ) {
				$this->current_template_id = $custom_template;
				return $this->getTemplatePath( 'pages/404', $template );
			}
		}

		// search page
		if ( is_search() ) {
			$sep             = Builder_Template_Helper::separator();
			$custom_template = Builder_Template_Helper::resolve_template_for_request( 'page' . $sep . 'search' );
			if ( ! $custom_template ) {
				$custom_template = $this->get_template_id( 'search', 'page' );
			}
			if ( $custom_template ) {
				$this->current_template_id = $custom_template;
				return $this->getTemplatePath( 'pages/search', $template );
			}
		}
		// front page
		// if (is_front_page()) {
		//     if ($custom_template = $this->get_template_id('home', 'page')) {
		//         $this->current_template_id = $custom_template;
		//         return $this->getTemplatePath('pages/home', $template);
		//     }
		// }

		// Custom post types - single
		if ( is_single() && ! in_array( get_post_type(), [ 'post', 'page' ] ) ) {
			$post_type = get_post_type();
			if ( $custom_template = $this->get_template_id( 'single', $post_type ) ) {
				$this->current_template_id = $custom_template;
				// Try specific template first, then fall back to generic custom template
				if ( $template_path = $this->getTemplatePath( "custom/{$post_type}/single", '' ) ) {
					return $template_path;
				}
				return $this->getTemplatePath( "custom/single", $template );
			}
		}

		// Custom post types - archive
		if ( is_post_type_archive() && ! in_array( get_post_type(), [ 'post', 'page' ], true ) ) {
			$post_type       = get_post_type();
			$sep             = Builder_Template_Helper::separator();
			$custom_template = Builder_Template_Helper::resolve_template_for_request( $post_type . $sep . 'archive' );
			if ( ! $custom_template ) {
				$custom_template = $this->get_template_id( 'archive', $post_type );
			}
			if ( $custom_template ) {
				$this->current_template_id = $custom_template;
				// Try specific template first, then fall back to generic custom template
				if ( $template_path = $this->getTemplatePath( "custom/{$post_type}/archive", '' ) ) {
					return $template_path;
				}
				return $this->getTemplatePath( "custom/archive", $template );
			}
		}

		// Custom post types - taxonomy archives
		if ( is_tax() ) {
			$taxonomy = get_queried_object();
			if ( $taxonomy && isset( $taxonomy->taxonomy ) ) {
				$post_types = get_taxonomy( $taxonomy->taxonomy )->object_type;
				foreach ( $post_types as $post_type ) {
					if ( ! in_array( $post_type, [ 'post', 'page' ] ) ) {
						if ( $custom_template = $this->get_template_id( $taxonomy->taxonomy, $post_type ) ) {
							$this->current_template_id = $custom_template;
							// Try specific template first, then fall back to generic custom template
							if ( $template_path = $this->getTemplatePath( "custom/{$post_type}/{$taxonomy->taxonomy}", '' ) ) {
								return $template_path;
							}
							return $this->getTemplatePath( "custom/archive", $template );
						}
					}
				}
			}
		}


		// themes header
		if ( is_page() && ! is_page_template() && 'themes' == get_post_type() ) {
			if ( $custom_template = $this->get_template_id( 'header', 'themes' ) ) {
				$this->current_template_id = $custom_template;
				return $this->getTemplatePath( 'themes/header', $template );
			}
		}

		// WooCommerce pages — only when WooCommerce is active
		if ( class_exists( 'WooCommerce' ) ) {

			// Cart page — check before checkout because is_checkout() can return true on cart too
			if ( function_exists( 'is_cart' ) && is_cart() ) {
				if ( $custom_template = $this->get_template_id( 'cart', 'product' ) ) {
					$this->current_template_id = $custom_template;
					return $this->getTemplatePath( 'woocommerce/cart', $template );
				}
			}

			// Thank You / Order Received page
			if ( function_exists( 'is_order_received_page' ) && is_order_received_page() ) {
				if ( $custom_template = $this->get_template_id( 'thankyou', 'product' ) ) {
					$this->current_template_id = $custom_template;
					return $this->getTemplatePath( 'woocommerce/thankyou', $template );
				}
			}

			// Checkout page
			if ( function_exists( 'is_checkout' ) && is_checkout() ) {
				if ( $custom_template = $this->get_template_id( 'checkout', 'product' ) ) {
					$this->current_template_id = $custom_template;
					return $this->getTemplatePath( 'woocommerce/checkout', $template );
				}
			}

			// My Account — Orders endpoint (/my-account/orders/).
			// Must come before the generic myaccount check since is_account_page() is true for all endpoints.
			if ( function_exists( 'is_account_page' ) && is_account_page() && function_exists( 'is_wc_endpoint_url' ) && is_wc_endpoint_url( 'orders' ) ) {
				if ( $custom_template = $this->get_template_id( 'orders', 'product' ) ) {
					$this->current_template_id = $custom_template;
					return $this->getTemplatePath( 'woocommerce/orders', $template );
				}
			}

			// My Account dashboard page (/my-account/).
			if ( function_exists( 'is_account_page' ) && is_account_page() ) {
				if ( $custom_template = $this->get_template_id( 'myaccount', 'product' ) ) {
					$this->current_template_id = $custom_template;
					return $this->getTemplatePath( 'woocommerce/my-account', $template );
				}
			}

			// Product Category page.
			if ( is_tax( 'product_cat' ) ) {
				$sep             = Builder_Template_Helper::separator();
				$legacy_types    = [ 'product' . $sep . 'category', 'product' . $sep . 'archive' ];
				$custom_template = Builder_Template_Helper::resolve_template_for_request( 'product' . $sep . 'shop', $legacy_types );
				if ( ! $custom_template ) {
					$custom_template = $this->get_template_id( 'category', 'product' );
				}
				if ( $custom_template ) {
					$this->current_template_id = $custom_template;
					return $this->getTemplatePath( 'woocommerce/archive-product', $template );
				}
			}

			// Product Tag page.
			if ( is_tax( 'product_tag' ) ) {
				$sep             = Builder_Template_Helper::separator();
				$legacy_types    = [ 'product' . $sep . 'tag', 'product' . $sep . 'archive' ];
				$custom_template = Builder_Template_Helper::resolve_template_for_request( 'product' . $sep . 'shop', $legacy_types );
				if ( ! $custom_template ) {
					$custom_template = $this->get_template_id( 'tag', 'product' );
				}
				if ( $custom_template ) {
					$this->current_template_id = $custom_template;
					return $this->getTemplatePath( 'woocommerce/archive-product', $template );
				}
			}

			// Shop / Product Archive page.
			// is_shop() covers the main WooCommerce shop page; is_post_type_archive('product') covers
			// any additional product archive URL. Both use the same archive-product template.
			if ( ( function_exists( 'is_shop' ) && is_shop() ) || is_post_type_archive( 'product' ) ) {
				$sep             = Builder_Template_Helper::separator();
				$legacy_types    = [ 'product' . $sep . 'archive', 'product' . $sep . 'category', 'product' . $sep . 'tag' ];
				$custom_template = Builder_Template_Helper::resolve_template_for_request( 'product' . $sep . 'shop', $legacy_types );
				if ( ! $custom_template ) {
					$custom_template = $this->get_template_id( 'shop', 'product' );
				}
				if ( $custom_template ) {
					$this->current_template_id = $custom_template;
					return $this->getTemplatePath( 'woocommerce/archive-product', $template );
				}
			}
		}

		return $template;
	}


	public function getThemeTemplatePath( $slug ) {

		$fullPath = get_template_directory() . "/bdthemes-element-pack/$slug";
		if ( file_exists( $fullPath ) ) {
			return $fullPath;
		}
	}

	public function getPluginTemplatePath( $slug ) {

		$fullPath = BDTEP_PATH . "includes/builder/templates/$slug";
		if ( file_exists( $fullPath ) ) {
			return $fullPath;
		}
	}


	/**
	 * Get Template Path ID
	 *
	 * @param $slug
	 * @param $postType
	 *
	 * @return mixed|void|null
	 */
	public function get_template_id( $slug, $postType = false ) {

		if ( null !== $this->preview_locked_template_id ) {
			return $this->preview_locked_template_id;
		}

		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		if ( ! empty( $_GET['preview'] ) && isset( $_GET['bdt_template_id'], $_GET['preview_nonce'] ) ) {
			$bdt_template_id = absint( wp_unslash( $_GET['bdt_template_id'] ) );
			$nonce_raw       = sanitize_text_field( wp_unslash( $_GET['preview_nonce'] ) );

			if ( $bdt_template_id > 0 && '' !== trim( $nonce_raw ) ) {
				$nonce_raw      = trim( $nonce_raw );
				$is_demo_bypass = ( 'verified' === $nonce_raw );
				$nonce_verified = $is_demo_bypass
					? (bool) apply_filters( 'element_pack/preview/verified_bypass', false )
					: wp_verify_nonce( $nonce_raw, 'template_preview_' . $bdt_template_id );

				if ( $nonce_verified ) {
					if ( $is_demo_bypass ) {
						$this->preview_locked_template_id = $bdt_template_id;
						$this->current_template_id       = $bdt_template_id;

						return $this->preview_locked_template_id;
					}

					$template_type_meta = get_post_meta( $bdt_template_id, Meta::TEMPLATE_TYPE, true );
					if ( ! empty( $template_type_meta ) ) {
						$template_segments = explode( Builder_Template_Helper::separator(), $template_type_meta );
						if ( count( $template_segments ) >= 2 ) {
							$meta_post_type = $template_segments[0];
							$meta_slug      = $template_segments[1];
							$slug_matches   = ( strtolower( (string) $meta_slug ) === strtolower( (string) $slug ) );
							if ( ! $slug_matches && 'post' === strtolower( (string) $meta_post_type ) && 'archive' === $meta_slug ) {
								$slug_matches = in_array(
									strtolower( (string) $slug ),
									[ 'archive', 'category', 'tag', 'author', 'date' ],
									true
								);
							}
							if ( ! $slug_matches && 'product' === strtolower( (string) $meta_post_type ) && in_array( $meta_slug, [ 'shop', 'archive' ], true ) ) {
								$slug_matches = in_array(
									strtolower( (string) $slug ),
									[ 'shop', 'archive', 'category', 'tag' ],
									true
								);
							}
							$type_matches   = ( false === $postType || strtolower( (string) $meta_post_type ) === strtolower( (string) $postType ) );
							if ( $slug_matches && $type_matches ) {
								$this->preview_locked_template_id = $bdt_template_id;
								$this->current_template_id       = $bdt_template_id;

								return $this->preview_locked_template_id;
							}
						}
					}
				}
			}
		}
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		if ( 'post' == $postType ) {
			$patterns = [
				'single' 	=> ['post', '_bdthemes_builder_post|single__'],
				'archive' 	=> ['post', '_bdthemes_builder_post|archive__'],
				'category' 	=> ['post', '_bdthemes_builder_post|category__'],
				'tag' 		=> ['post', '_bdthemes_builder_post|tag__'],
				'author' 	=> ['post', '_bdthemes_builder_post|author__'],
				'date' 		=> ['post', '_bdthemes_builder_post|date__'],
			];
		} elseif ( 'page' == $postType ) {
			$patterns = [
				'single'    => ['page', '_bdthemes_builder_page|single__'],
				'404'     	=> ['page', '_bdthemes_builder_page|404__'],
				'search'    => ['page', '_bdthemes_builder_page|search__'],
			];
		} elseif ( 'product' == $postType ) {
			$patterns = [
				'shop'      => ['product', '_bdthemes_builder_product|shop__'],
				'single'    => ['product', '_bdthemes_builder_product|single__'],
				'archive'   => ['product', '_bdthemes_builder_product|archive__'],
				'category'  => ['product', '_bdthemes_builder_product|category__'],
				'tag'       => ['product', '_bdthemes_builder_product|tag__'],
				'cart'      => ['product', '_bdthemes_builder_product|cart__'],
				'checkout'  => ['product', '_bdthemes_builder_product|checkout__'],
				'myaccount' => ['product', '_bdthemes_builder_product|myaccount__'],
				'orders'    => ['product', '_bdthemes_builder_product|orders__'],
				'thankyou'  => ['product', '_bdthemes_builder_product|thankyou__'],
			];
		} else {
			// Handle custom post types
			$patterns = [
				'single' 	=> [$postType, "_bdthemes_builder_{$postType}|single__"],
				'archive' 	=> [$postType, "_bdthemes_builder_{$postType}|archive__"],
			];
			
			// Add taxonomy patterns for custom post types
			$taxonomies = get_object_taxonomies( $postType, 'objects' );
			foreach ( $taxonomies as $taxonomy ) {
				if ( $taxonomy->public && $taxonomy->show_ui ) {
					$patterns[ $taxonomy->name ] = [$postType, "_bdthemes_builder_{$postType}|{$taxonomy->name}__"];
				}
			}
		}
	
		if (isset($patterns[$slug]) && $postType === $patterns[$slug][0]) {
			$results = Builder_Template_Helper::searchTemplateOptions($patterns[$slug][1]);
	
			$option_values = array_map(fn($result) => $result->option_value, $results);
			$slug = !empty($option_values) ? "{$slug}__" . end($option_values) : null;
		}


		$templateId                = Builder_Template_Helper::getTemplate( $slug, $postType );
		$this->current_template_id = apply_filters( 'bdthemes-templates-builder/custom-template', $templateId );

		return $this->current_template_id;
	}

	/**
	 * Get Template Path
	 *
	 * @param $slug
	 * @param $default
	 *
	 * @return mixed|string|void
	 */
	protected function getTemplatePath( $slug, $default = '' ) {
		$phpSlug = "{$slug}.php";

		if ( $template = $this->getThemeTemplatePath( $phpSlug ) ) {
			return $template;
		}

		if ( $template = $this->getPluginTemplatePath( $phpSlug ) ) {
			return $template;
		}

		return $default;
	}
}


Builder_Integration::instance();
