<?php

namespace ElementPack\Includes\Builder;

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

use ElementPack\Includes\Builder\Builder_Template_Helper;
use ElementPack\Includes\Builder\Meta;
use ElementPack\Includes\Builder\Template_Conditions;

/**
 * Full-screen Theme Builder on edit.php?post_type=bdt-template-builder (Elementor-style).
 *
 * @package ElementPack
 */
class Theme_Builder_Admin {

	/** @deprecated Kept for redirects only. */
	const PAGE_SLUG = 'bdt-ep-theme-builder';

	public static function init() {
		add_action( 'admin_init', [ __CLASS__, 'redirect_legacy_page' ] );
		add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue' ], 15 );
		add_action( 'admin_head', [ __CLASS__, 'print_hide_list_styles' ] );
		// Must run inside #wpbody-content (before .wrap). admin_footer runs after #wpbody is closed, which breaks layout.
		add_action( 'all_admin_notices', [ __CLASS__, 'render_app_markup' ], 5 );
		// Before add_classic_list_visual_link: keep All / Published / Trash on classic list (?bdt_tb_list=1).
		add_filter( 'views_edit-' . Meta::POST_TYPE, [ __CLASS__, 'inject_list_mode_into_status_view_links' ], 5 );
		add_filter( 'views_edit-' . Meta::POST_TYPE, [ __CLASS__, 'add_classic_list_visual_link' ] );
		add_action( 'wp_ajax_bdthemes_builder_save_conditions', [ __CLASS__, 'ajax_save_conditions' ] );
		add_action( 'wp_ajax_bdthemes_builder_tb_rename', [ __CLASS__, 'ajax_rename_template' ] );
		add_action( 'wp_ajax_bdthemes_builder_tb_trash', [ __CLASS__, 'ajax_trash_template' ] );
		add_action( 'wp_ajax_bdt_ep_theme_builder_export', [ __CLASS__, 'ajax_export_template' ] );
	}

	/**
	 * Append bdt_tb_list=1 to status links (All / Published / Trash) so they stay on the posts list
	 * instead of reloading the full-screen Visual Theme Builder.
	 *
	 * @param array<string, string> $views Views.
	 * @return array<string, string>
	 */
	public static function inject_list_mode_into_status_view_links( $views ) {
		if ( ! is_array( $views ) ) {
			return $views;
		}

		$pt = Meta::POST_TYPE;

		foreach ( $views as $key => $html ) {
			$views[ $key ] = preg_replace_callback(
				'/href\s*=\s*(["\'])([^"\']*)\1/i',
				static function ( $m ) use ( $pt ) {
					$raw = html_entity_decode( $m[2], ENT_QUOTES | ENT_HTML5, 'UTF-8' );
					if ( '' === $raw ) {
						return $m[0];
					}

					$query = wp_parse_url( $raw, PHP_URL_QUERY );
					if ( ! is_string( $query ) || '' === $query ) {
						return $m[0];
					}

					parse_str( $query, $qargs );
					if ( empty( $qargs['post_type'] ) || $qargs['post_type'] !== $pt ) {
						return $m[0];
					}
					if ( isset( $qargs['bdt_tb_list'] ) && '1' === (string) $qargs['bdt_tb_list'] ) {
						return $m[0];
					}

					$new = add_query_arg( 'bdt_tb_list', '1', $raw );

					return 'href=' . $m[1] . esc_url( $new ) . $m[1];
				},
				$html
			);
		}

		return $views;
	}

	/**
	 * When using table list (?bdt_tb_list=1), offer a link back to the visual builder.
	 *
	 * @param array<string, string> $views Views.
	 * @return array<string, string>
	 */
	public static function add_classic_list_visual_link( $views ) {
		if ( ! is_array( $views ) ) {
			return $views;
		}
		if ( ! isset( $_GET['bdt_tb_list'] ) || '1' !== $_GET['bdt_tb_list'] ) {
			return $views;
		}
		$url                    = admin_url( 'edit.php?post_type=' . Meta::POST_TYPE );
		$views['bdt_visual_tb'] = '<a href="' . esc_url( $url ) . '" class="bdt-tb-switch-visual">' . esc_html__( 'Visual Theme Builder', 'bdthemes-element-pack' ) . '</a>';
		return $views;
	}

	/**
	 * Old bookmarks: admin.php?page=bdt-ep-theme-builder → CPT list (visual).
	 */
	public static function redirect_legacy_page() {
		if ( ! is_admin() || ! isset( $_GET['page'] ) ) {
			return;
		}
		if ( self::PAGE_SLUG !== sanitize_key( wp_unslash( $_GET['page'] ) ) ) {
			return;
		}
		$pto = get_post_type_object( Meta::POST_TYPE );
		if ( ! $pto || ! current_user_can( $pto->cap->edit_posts ) ) {
			return;
		}
		wp_safe_redirect( admin_url( 'edit.php?post_type=' . Meta::POST_TYPE ) );
		exit;
	}

	/**
	 * Visual Theme Builder on edit.php?post_type=bdt-template-builder unless ?bdt_tb_list=1.
	 */
	public static function is_visual_mode() {
		if ( ! is_admin() ) {
			return false;
		}
		global $pagenow;
		if ( 'edit.php' !== $pagenow ) {
			return false;
		}
		if ( ! isset( $_GET['post_type'] ) || Meta::POST_TYPE !== sanitize_key( wp_unslash( $_GET['post_type'] ) ) ) {
			return false;
		}
		if ( isset( $_GET['bdt_tb_list'] ) && '1' === $_GET['bdt_tb_list'] ) {
			return false;
		}

		// Any list-table context (status filters, search, pagination, template-type dropdown) stays on classic list.
		if ( isset( $_GET['post_status'] ) && '' !== trim( (string) wp_unslash( $_GET['post_status'] ) ) ) {
			return false;
		}
		if ( isset( $_GET['paged'] ) && (int) $_GET['paged'] > 1 ) {
			return false;
		}
		if ( ! empty( $_GET['s'] ) ) {
			return false;
		}
		$type_filter = isset( $_GET['type'] ) ? sanitize_text_field( wp_unslash( $_GET['type'] ) ) : '';
		if ( '' !== $type_filter && 'all' !== $type_filter ) {
			return false;
		}

		if ( isset( $_GET['author'] ) && '' !== trim( (string) wp_unslash( $_GET['author'] ) ) ) {
			return false;
		}

		$pto = get_post_type_object( Meta::POST_TYPE );
		if ( ! $pto || ! current_user_can( $pto->cap->edit_posts ) ) {
			return false;
		}
		return true;
	}

	public static function enqueue( $hook ) {
		if ( 'edit.php' !== $hook || ! self::is_visual_mode() ) {
			return;
		}

		wp_register_script( 'select2', BDTEP_ADMIN_ASSETS_URL . 'vendor/select2/select2.min.js', [ 'jquery' ], '4.0.7-full', true );
		wp_register_style( 'select2', BDTEP_ADMIN_ASSETS_URL . 'vendor/select2/select2.min.css', [], '4.0.7' );
		wp_enqueue_script( 'select2' );
		wp_enqueue_style( 'select2' );

		// Modal create/update + Select2 for conditions rely on ep-builder handlers.
		if ( ! wp_script_is( 'ep-builder', 'enqueued' ) ) {
			wp_enqueue_style( 'ep-builder', BDTEP_ADMIN_ASSETS_URL . 'css/ep-builder.css', [], BDTEP_VER );
			wp_enqueue_script( 'ep-builder', BDTEP_ADMIN_ASSETS_URL . 'js/ep-builder.min.js', [ 'jquery', 'select2' ], BDTEP_VER, true );
			wp_localize_script(
				'ep-builder',
				'ElementPackConfigBuilder',
				[
					'ajaxurl'    => admin_url( 'admin-ajax.php' ),
					'nonce'      => wp_create_nonce( 'element_pack_builder_nonce' ),
					'resturl'    => rest_url( 'bdt/v1/' ),
					'restnonce'  => wp_create_nonce( 'wp_rest' ),
					'promoShown' => get_option( 'bdt_usk_promo_shown', false ) ? true : false,
				]
			);
		}

		$tb_css_deps = [];
		if ( self::uses_elementor_sidebar_icons() ) {
			$icon_ver = class_exists( '\Elementor\Icons_Manager' ) ? \Elementor\Icons_Manager::ELEMENTOR_ICONS_VERSION : '5.48.0';
			if ( ! wp_style_is( 'elementor-icons', 'registered' ) ) {
				wp_register_style(
					'elementor-icons',
					ELEMENTOR_ASSETS_URL . 'lib/eicons/css/elementor-icons.min.css',
					[],
					$icon_ver
				);
			}
			$tb_css_deps[] = 'elementor-icons';
		}

		wp_enqueue_style(
			'bdt-ep-theme-builder',
			BDTEP_ADMIN_ASSETS_URL . 'css/ep-theme-builder.css',
			$tb_css_deps,
			BDTEP_VER
		);

		wp_enqueue_script(
			'bdt-ep-theme-builder',
			BDTEP_ADMIN_ASSETS_URL . 'js/ep-theme-builder.min.js',
			[ 'jquery', 'select2', 'ep-builder' ],
			BDTEP_VER,
			true
		);

		wp_localize_script(
			'bdt-ep-theme-builder',
			'bdtThemeBuilder',
			self::get_js_config()
		);
	}

	public static function print_hide_list_styles() {
		if ( ! self::is_visual_mode() ) {
			return;
		}
		$pt = esc_attr( Meta::POST_TYPE );
		echo '<style id="bdt-ep-theme-builder-hide-list">'
			. 'body.edit-php.post-type-' . $pt . ' #wpbody-content > .wrap { display: none !important; }'
			. '</style>';
	}

	public static function render_app_markup() {
		if ( ! self::is_visual_mode() ) {
			return;
		}
		$view_file = BDTEP_PATH . 'includes/builder/admin/views/theme-builder.php';
		if ( file_exists( $view_file ) ) {
			require $view_file;
		}
	}

	/**
	 * @return array<string, mixed>
	 */
	public static function get_js_config() {
		$list_url = admin_url( 'edit.php?post_type=' . Meta::POST_TYPE . '&bdt_tb_list=1' );

		return [
			'useElementorIcons' => self::uses_elementor_sidebar_icons(),
			'isProActivated'  => function_exists( 'element_pack_pro_activated' ) && element_pack_pro_activated(),
			'allPartsPlaceholderBase' => trailingslashit( esc_url_raw( BDTEP_URL . 'assets/images/theme-builder' ) ),
			'allPartsPlaceholderVer'  => (string) BDTEP_VER,
			'ajaxurl'         => admin_url( 'admin-ajax.php' ),
			'nonce'           => wp_create_nonce( 'element_pack_builder_nonce' ),
			'nonceEpBuilder'  => wp_create_nonce( 'ep-builder' ),
			'directNewBase'   => esc_url_raw(
				add_query_arg(
					[
						'action'   => 'bdt_ep_theme_builder_new',
						'_wpnonce' => wp_create_nonce( 'bdt_ep_theme_builder_new' ),
					],
					admin_url( 'admin-post.php' )
				)
			),
			'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' ),
			'tableViewUrl'    => $list_url,
			'packSettingsUrl' => admin_url( 'admin.php?page=element_pack_options' ),
			'packLicenseUrl'  => esc_url_raw( admin_url( 'admin.php?page=element_pack_options' ) . '#element_pack_license_settings' ),
			'pricingPageUrl'  => esc_url_raw(
				apply_filters(
					'element_pack_theme_builder_pricing_url',
					'https://www.elementpack.pro/pricing/?utm_source=theme_builder&utm_medium=plugin_admin'
				)
			),
			'helpUrl'         => 'https://bdthemes.com/all-knowledge-base-of-element-pack/',
			'strings'         => [
				'themeBuilder'    => __( 'Theme Builder', 'bdthemes-element-pack' ),
				'allParts'        => __( 'All Parts', 'bdthemes-element-pack' ),
				'siteParts'       => __( 'Site Parts', 'bdthemes-element-pack' ),
				'globalParts'     => __( "Your Site's Global Parts", 'bdthemes-element-pack' ),
				'addNew'          => __( 'Add New', 'bdthemes-element-pack' ),
				'switchTable'     => __( 'Switch to table view', 'bdthemes-element-pack' ),
				'edit'            => __( 'Edit', 'bdthemes-element-pack' ),
				'editConditions'  => __( 'Edit Conditions', 'bdthemes-element-pack' ),
				'instances'       => __( 'Instances', 'bdthemes-element-pack' ),
				'active'          => __( 'Active', 'bdthemes-element-pack' ),
				'inactive'        => __( 'Inactive', 'bdthemes-element-pack' ),
				'draft'           => __( 'draft', 'bdthemes-element-pack' ),
				'back'            => __( 'Back', 'bdthemes-element-pack' ),
				'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' ),
				/* Translators: optional search field for Singular › Posts/Pages/Media conditions. */
				'conditionRefinePlaceholder' => __( 'Search', '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' ),
				'entireSite'      => __( 'Entire site', 'bdthemes-element-pack' ),
				'archive'         => __( 'Archives', 'bdthemes-element-pack' ),
				'singular'        => __( 'Singular', 'bdthemes-element-pack' ),
				'close'           => __( 'Close', 'bdthemes-element-pack' ),
				'help'            => __( 'Help', 'bdthemes-element-pack' ),
				'previewFrame'    => __( 'Live template preview', 'bdthemes-element-pack' ),
				'preview'         => __( 'Preview', 'bdthemes-element-pack' ),
				'noTemplates'     => __( 'No templates found. Create one with Add New.', 'bdthemes-element-pack' ),
				'loading'         => __( 'Loading…', 'bdthemes-element-pack' ),
				'addNewHeading'   => __( 'Start customizing every part of your site', 'bdthemes-element-pack' ),
				'loopUnavailable'   => __( 'This template type is not available in Theme Builder yet.', 'bdthemes-element-pack' ),
				'moreActions'       => __( 'More actions', 'bdthemes-element-pack' ),
				'addNewTemplateType'=> __( 'Add new %s', 'bdthemes-element-pack' ),
				'exportTemplate'    => __( 'Export', 'bdthemes-element-pack' ),
				'trashMenu'         => __( 'Trash', 'bdthemes-element-pack' ),
				'renameMenu'        => __( 'Rename', 'bdthemes-element-pack' ),
				'renameSitePart'    => __( 'Rename Site Part', 'bdthemes-element-pack' ),
				'change'            => __( 'Change', 'bdthemes-element-pack' ),
				'cancel'            => __( 'Cancel', 'bdthemes-element-pack' ),
				'moveItemToTrash'   => __( 'Move Item To Trash', 'bdthemes-element-pack' ),
				'moveToTrashButton' => __( 'Move to Trash', 'bdthemes-element-pack' ),
				/* translators: %s: template title */
				'moveToTrashConfirm'=> __( 'Are you sure you want to move this item to trash: "%s"', 'bdthemes-element-pack' ),
				'renameFailed'      => __( 'Could not rename the template.', 'bdthemes-element-pack' ),
				'trashFailed'       => __( 'Could not move the template to trash.', 'bdthemes-element-pack' ),
				'exportUnavailable' => __( 'Export requires Elementor.', 'bdthemes-element-pack' ),
				'licenseRequiredNewTemplate' => __( 'An active Element Pack Pro license is required to add new templates. Open Element Pack in the WordPress admin menu to activate your license.', 'bdthemes-element-pack' ),
				'licensePopoverTitle'         => __( 'Pro license required', 'bdthemes-element-pack' ),
				'licensePopoverActivate'      => __( 'Active License', 'bdthemes-element-pack' ),
				'licensePopoverPricing'       => __( 'Get License', 'bdthemes-element-pack' ),
				'licensePopoverDismiss'       => __( 'Got it', 'bdthemes-element-pack' ),
			],
			'addNewCards'     => self::get_add_new_cards(),
			'nav'             => self::get_nav_items(),
			'locationOptions' => self::get_location_options(),
			'singularOptions' => self::get_singular_suboptions(),
			'archiveOptions'  => self::get_archive_suboptions(),
			'wooOptions'      => self::get_woo_suboptions(),
			'templates'       => self::collect_templates(),
		];
	}

	/**
	 * Theme Builder sidebar uses Elementor eicons when Elementor (and its icon assets) are available.
	 */
	private static function uses_elementor_sidebar_icons(): bool {
		return class_exists( '\Elementor\Plugin' ) && defined( 'ELEMENTOR_ASSETS_URL' );
	}

	/**
	 * Cards for the Elementor-style “Add new” grid (ordered like Site Parts).
	 *
	 * @return array<int, array{type: string, label: string, wf: string, disabled?: bool, disabledReason?: string}>
	 */
	public static function get_add_new_cards() {
		$sep = Builder_Template_Helper::separator();

		$definitions = [
			[
				'type' => 'themes' . $sep . 'header',
				'label' => __( 'Header', 'bdthemes-element-pack' ),
				'wf'    => 'header',
			],
			[
				'type' => 'themes' . $sep . 'footer',
				'label' => __( 'Footer', 'bdthemes-element-pack' ),
				'wf'    => 'footer',
			],
			[
				'type' => 'post' . $sep . 'single',
				'label' => __( 'Single Post', 'bdthemes-element-pack' ),
				'wf'    => 'single_post',
			],
			[
				'type' => 'page' . $sep . 'single',
				'label' => __( 'Single Page', 'bdthemes-element-pack' ),
				'wf'    => 'single_page',
			],
			[
				'type' => 'post' . $sep . 'archive',
				'label' => __( 'Archive', 'bdthemes-element-pack' ),
				'wf'    => 'archive',
			],
			[
				'type' => 'page' . $sep . 'search',
				'label' => __( 'Search Results', 'bdthemes-element-pack' ),
				'wf'    => 'search',
			],
			[
				'type'         => 'product' . $sep . 'single',
				'label'        => __( 'Single Product', 'bdthemes-element-pack' ),
				'wf'           => 'single_product',
				'requires_wc'  => true,
			],
			[
				'type'         => 'product' . $sep . 'shop',
				'label'        => __( 'Products Archive', 'bdthemes-element-pack' ),
				'wf'           => 'products_archive',
				'requires_wc'  => true,
			],
			[
				'type' => 'page' . $sep . '404',
				'label' => __( 'Error 404', 'bdthemes-element-pack' ),
				'wf'    => 'error_404',
			],
		];

		$cards = [];
		$seen  = [];

		foreach ( $definitions as $row ) {
			if ( ! empty( $row['requires_wc'] ) && ! class_exists( 'WooCommerce' ) ) {
				continue;
			}

			if ( ! empty( $row['disabled'] ) ) {
				$cards[] = [
					'type'             => '',
					'label'            => $row['label'],
					'wf'               => $row['wf'],
					'disabled'         => true,
					'disabledReason'   => __( 'Loop templates are not available in Element Pack Theme Builder yet.', 'bdthemes-element-pack' ),
				];
				continue;
			}

			if ( ! Builder_Template_Helper::getTemplateByIndex( $row['type'] ) ) {
				continue;
			}

			$cards[] = [
				'type'  => $row['type'],
				'label' => $row['label'],
				'wf'    => $row['wf'],
			];
			$seen[] = $row['type'];
		}

		$flat = Builder_Template_Helper::templates( true );
		foreach ( $flat as $type_key => $label ) {
			if ( in_array( $type_key, $seen, true ) ) {
				continue;
			}
			$cards[] = [
				'type'  => $type_key,
				'label' => self::format_add_new_card_label( $type_key, (string) $label, $sep ),
				'wf'    => 'custom',
			];
		}

		return apply_filters( 'bdt_ep_theme_builder_add_new_cards', $cards );
	}

	/**
	 * Make fallback "Add New" card labels specific and unambiguous.
	 *
	 * @param string $type_key Full template key (e.g. post|category).
	 * @param string $label    Raw label from Builder_Template_Helper::templates( true ).
	 * @param string $sep      Template key separator.
	 */
	private static function format_add_new_card_label( $type_key, $label, $sep ) {
		$label = trim( (string) $label );
		if ( '' === $label ) {
			$label = $type_key;
		}

		$explicit = [
			'post' . $sep . 'category'    => __( 'Post Category Archive', 'bdthemes-element-pack' ),
			'post' . $sep . 'tag'         => __( 'Post Tag Archive', 'bdthemes-element-pack' ),
			'post' . $sep . 'author'      => __( 'Post Author Archive', 'bdthemes-element-pack' ),
			'post' . $sep . 'date'        => __( 'Post Date Archive', 'bdthemes-element-pack' ),
			'product' . $sep . 'archive'  => __( 'Product Archive', 'bdthemes-element-pack' ),
			'product' . $sep . 'category' => __( 'Product Category Archive', 'bdthemes-element-pack' ),
			'product' . $sep . 'tag'      => __( 'Product Tag Archive', 'bdthemes-element-pack' ),
			'product' . $sep . 'cart'     => __( 'Cart Page', 'bdthemes-element-pack' ),
			'product' . $sep . 'checkout' => __( 'Checkout Page', 'bdthemes-element-pack' ),
			'product' . $sep . 'myaccount' => __( 'My Account Page', 'bdthemes-element-pack' ),
			'product' . $sep . 'orders'   => __( 'Orders Page', 'bdthemes-element-pack' ),
			'product' . $sep . 'thankyou' => __( 'Thank You Page', 'bdthemes-element-pack' ),
		];
		if ( isset( $explicit[ $type_key ] ) ) {
			return $explicit[ $type_key ];
		}

		$parts = explode( $sep, $type_key, 2 );
		if ( 2 !== count( $parts ) ) {
			return $label;
		}

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

		if ( 'themes' === $group ) {
			return $label;
		}

		$generic_slugs = [ 'single', 'archive', 'category', 'tag', 'author', 'date' ];
		if ( ! in_array( $slug, $generic_slugs, true ) ) {
			return $label;
		}

		$group_label = self::template_group_display_name( $group );
		if ( '' === $group_label ) {
			return $label;
		}

		if ( false !== stripos( $label, $group_label ) ) {
			return $label;
		}

		return sprintf(
			/* translators: 1: content type label, 2: condition label */
			__( '%1$s %2$s', 'bdthemes-element-pack' ),
			$group_label,
			$label
		);
	}

	/**
	 * Human label for template key group (post type).
	 *
	 * @param string $group Template key group.
	 */
	private static function template_group_display_name( $group ) {
		if ( 'post' === $group ) {
			return __( 'Post', 'bdthemes-element-pack' );
		}
		if ( 'page' === $group ) {
			return __( 'Page', 'bdthemes-element-pack' );
		}
		if ( 'product' === $group ) {
			return __( 'Product', 'bdthemes-element-pack' );
		}

		$pto = get_post_type_object( $group );
		if ( $pto instanceof \WP_Post_Type ) {
			if ( ! empty( $pto->labels->singular_name ) ) {
				return (string) $pto->labels->singular_name;
			}
			if ( ! empty( $pto->label ) ) {
				return (string) $pto->label;
			}
		}

		return (string) ucwords( str_replace( '_', ' ', $group ) );
	}

	/**
	 * @return array<int, array<string, mixed>>
	 */
	public static function get_nav_items() {
		$nav = [
			[
				'id'    => 'all',
				'label' => __( 'All Parts', 'bdthemes-element-pack' ),
				'types' => null,
			],
			[
				'section' => __( 'Site Parts', 'bdthemes-element-pack' ),
			],
			[
				'id'    => 'header',
				'label' => __( 'Header', 'bdthemes-element-pack' ),
				'types' => [ 'themes|header' ],
			],
			[
				'id'    => 'footer',
				'label' => __( 'Footer', 'bdthemes-element-pack' ),
				'types' => [ 'themes|footer' ],
			],
			[
				'id'    => 'single_post',
				'label' => __( 'Single Post', 'bdthemes-element-pack' ),
				'types' => [ 'post|single' ],
			],
			[
				'id'    => 'single_page',
				'label' => __( 'Single Page', 'bdthemes-element-pack' ),
				'types' => [ 'page|single' ],
			],
			[
				'id'    => 'archive',
				'label' => __( 'Archive', 'bdthemes-element-pack' ),
				'types' => [ 'post|archive', 'post|category', 'post|tag', 'post|author', 'post|date' ],
			],
			[
				'id'    => 'search',
				'label' => __( 'Search Results', 'bdthemes-element-pack' ),
				'types' => [ 'page|search' ],
			],
		];

		if ( class_exists( 'WooCommerce' ) ) {
			$woo_sep = Builder_Template_Helper::separator();
			$nav[] = [
				'id'    => 'single_product',
				'label' => __( 'Single Product', 'bdthemes-element-pack' ),
				'types' => [ 'product|single' ],
			];
			$nav[] = [
				'id'    => 'products_archive',
				'label' => __( 'Products Archive', 'bdthemes-element-pack' ),
				'types' => [ 'product|shop', 'product|archive', 'product|category', 'product|tag' ],
			];

			$nav[] = [
				'id'    => 'woo_cart',
				'label' => __( 'Cart Page', 'bdthemes-element-pack' ),
				'types' => [ 'product' . $woo_sep . 'cart' ],
			];
			$nav[] = [
				'id'    => 'woo_checkout',
				'label' => __( 'Checkout Page', 'bdthemes-element-pack' ),
				'types' => [ 'product' . $woo_sep . 'checkout' ],
			];
			$nav[] = [
				'id'    => 'woo_myaccount',
				'label' => __( 'My Account Page', 'bdthemes-element-pack' ),
				'types' => [ 'product' . $woo_sep . 'myaccount' ],
			];
			$nav[] = [
				'id'    => 'woo_orders',
				'label' => __( 'Orders Page', 'bdthemes-element-pack' ),
				'types' => [ 'product' . $woo_sep . 'orders' ],
			];
			$nav[] = [
				'id'    => 'woo_thankyou',
				'label' => __( 'Thank You Page', 'bdthemes-element-pack' ),
				'types' => [ 'product' . $woo_sep . 'thankyou' ],
			];
		}

		$nav[] = [
			'id'    => 'error_404',
			'label' => __( 'Error 404', 'bdthemes-element-pack' ),
			'types' => [ 'page|404' ],
		];

		$templates = Builder_Template_Helper::templates();
		foreach ( $templates as $group => $items ) {
			if ( ! is_array( $items ) ) {
				continue;
			}
			if ( in_array( $group, [ 'themes', 'post', 'page', 'product' ], true ) ) {
				continue;
			}

			$pto  = get_post_type_object( $group );
			$lbl  = $pto && ! empty( $pto->labels->singular_name ) ? $pto->labels->singular_name : ucwords( str_replace( '_', ' ', $group ) );
			$keys = [];
			foreach ( array_keys( $items ) as $key ) {
				$keys[] = $group . Builder_Template_Helper::separator() . $key;
			}
			$nav[] = [
				'id'    => 'cpt_' . sanitize_key( $group ),
				'label' => $lbl,
				'types' => $keys,
			];
		}

		return apply_filters( 'bdt_ep_theme_builder_nav_items', $nav );
	}

	/**
	 * @return array<string, string>
	 */
	public static function get_location_options() {
		$opts = [
			'entire_site' => __( 'Entire site', 'bdthemes-element-pack' ),
			'archive'     => __( 'Archives', 'bdthemes-element-pack' ),
			'singular'    => __( 'Singular', 'bdthemes-element-pack' ),
		];
		if ( class_exists( 'WooCommerce' ) ) {
			$opts['woocommerce'] = __( 'WooCommerce', 'bdthemes-element-pack' );
		}
		return apply_filters( 'bdt_ep_theme_builder_location_options', $opts );
	}

	/**
	 * Grouped archive options for the JS dropdown (with optgroups).
	 *
	 * @return array<int, array<string, mixed>>
	 */
	public static function get_archive_suboptions() {
		return apply_filters(
			'bdt_ep_theme_builder_archive_options',
			Template_Conditions::archive_grouped_options()
		);
	}

	/**
	 * Grouped WooCommerce options for the JS dropdown.
	 *
	 * @return array<int, array<string, mixed>>
	 */
	public static function get_woo_suboptions() {
		if ( ! class_exists( 'WooCommerce' ) ) {
			return [];
		}
		return apply_filters(
			'bdt_ep_theme_builder_woo_options',
			Template_Conditions::woo_grouped_options()
		);
	}

	/**
	 * Grouped Singular options for the JS dropdown (with optgroups for Posts / Pages / Media / CPT / Other).
	 *
	 * @return array<int, array<string, mixed>>
	 */
	public static function get_singular_suboptions() {
		$post_types = get_post_types(
			[
				'public'  => true,
				'show_ui' => true,
			],
			'objects'
		);

		$cpt_extra = [];
		foreach ( $post_types as $slug => $obj ) {
			if ( ! $obj instanceof \WP_Post_Type ) {
				continue;
			}
			if ( in_array( $slug, [ 'post', 'page', 'attachment' ], true ) ) {
				continue;
			}
			// Products use Theme Builder › WooCommerce in Elementor, not Singular › All products.
			if ( class_exists( 'WooCommerce' ) && 'product' === $slug ) {
				continue;
			}
			$cpt_extra[ 'pt_' . $slug ] = $obj->labels->name;
		}

		return apply_filters(
			'bdt_ep_theme_builder_singular_options',
			Template_Conditions::singular_grouped_options( $cpt_extra )
		);
	}

	/**
	 * @return array<int, array<string, mixed>>
	 */
	public static function collect_templates() {
		$q = new \WP_Query(
			[
				'post_type'              => Meta::POST_TYPE,
				'post_status'            => [ 'publish', 'draft', 'pending' ],
				'posts_per_page'         => -1,
				'orderby'                => 'modified',
				'order'                  => 'DESC',
				'no_found_rows'          => true,
				'update_post_meta_cache' => false,
				'update_post_term_cache' => false,
			]
		);

		$out = [];
		foreach ( $q->posts as $post ) {
			$out[] = self::template_payload( $post );
		}

		return $out;
	}

	/**
	 * Frontend preview URL for a template (Elementor `elementor-preview` when available).
	 *
	 * @param int  $post_id        Template post ID.
	 * @param bool $for_card_embed When true, adds `bdt_tb_card_embed=1` for iframe use in Theme Builder cards.
	 * @return string Empty if unavailable.
	 */
	public static function get_template_preview_url( $post_id, $for_card_embed = false ) {
		$post_id = (int) $post_id;
		$post    = get_post( $post_id );
		if ( ! $post || Meta::POST_TYPE !== $post->post_type ) {
			return '';
		}
		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			return '';
		}

		if ( 'publish' === $post->post_status ) {
			$base = get_permalink( $post_id );
		} else {
			$base = get_preview_post_link( $post );
		}

		if ( ! $base ) {
			$base = add_query_arg( 'p', $post_id, home_url( '/' ) );
			if ( 'publish' !== $post->post_status ) {
				$base = add_query_arg( 'preview', 'true', $base );
			}
		}

		if ( class_exists( '\Elementor\Plugin' ) ) {
			$base = set_url_scheme(
				add_query_arg(
					[
						'elementor-preview' => $post_id,
						'ver'               => time(),
					],
					$base
				)
			);
		}

		if ( $for_card_embed ) {
			$base = add_query_arg( 'bdt_tb_card_embed', '1', $base );
		}

		return esc_url_raw( (string) apply_filters( 'bdt_ep_theme_builder_template_preview_url', $base, $post_id, $post ) );
	}

	/**
	 * @param \WP_Post $post Post object.
	 * @return array<string, mixed>
	 */
	public static function template_payload( \WP_Post $post ) {
		$type   = (string) get_post_meta( $post->ID, Meta::TEMPLATE_TYPE, true );
		$option = strtolower( Meta::TEMPLATE_ID . $type . '__' . $post->ID );
		$active = (bool) get_option( $option, false );

		$thumb = get_the_post_thumbnail_url( $post->ID, 'medium_large' );
		if ( ! $thumb ) {
			$thumb = '';
		}

		$author = get_the_author_meta( 'display_name', (int) $post->post_author );

		$sep = Builder_Template_Helper::separator();
		// Elementor Pro Theme Builder behaviour: every template type exposes
		// "Display Conditions" — Header/Footer/Single/Archive/Single Product/
		// Products Archive/Search/404/CPT singles & archives all share the same
		// rules editor. Only legacy "themes|*" combos other than header/footer
		// (none currently exist) are excluded.
		$supports_conditions = ( '' !== $type );
		$export_url = '';
		if ( class_exists( '\Elementor\Plugin' ) && self::user_can_export_template( $post ) ) {
			// wp_nonce_url() HTML-escapes &; broken when localized to JS for href.
			$export_base = add_query_arg(
				[
					'action' => 'bdt_ep_theme_builder_export',
					'post'   => $post->ID,
				],
				admin_url( 'admin-ajax.php' )
			);
			$export_url  = add_query_arg(
				'_wpnonce',
				wp_create_nonce( 'bdt_tb_export_' . $post->ID ),
				$export_base
			);
		}

		return [
			'id'                 => (int) $post->ID,
			'title'              => get_the_title( $post ),
			'type'               => $type,
			'typeLabel'          => Builder_Template_Helper::getTemplateByIndex( $type ) ?: $type,
			'status'             => $post->post_status,
			'isActive'           => $active,
			'date'               => get_the_date( get_option( 'date_format' ), $post ),
			'author'             => $author,
			'thumbnail'          => $thumb,
			'cardPreviewUrl'     => self::get_template_preview_url( $post->ID, true ),
			'exportUrl'          => $export_url ? (string) $export_url : '',
			'canTrash'           => current_user_can( 'delete_post', $post->ID ),
			'canRename'          => current_user_can( 'edit_post', $post->ID ),
			'editElementorUrl'   => add_query_arg(
				[
					'post'         => $post->ID,
					'action'       => 'elementor',
					'bdt-template' => 1,
				],
				admin_url( 'post.php' )
			),
			'supportsConditions' => $supports_conditions,
			'instancesLabel'     => $supports_conditions ? Template_Conditions::get_instances_label( $post->ID ) : '',
			'conditions'         => $supports_conditions ? Template_Conditions::get_rows( $post->ID ) : [],
		];
	}

	/**
	 * Elementor local source–style export permission check.
	 *
	 * @param \WP_Post $post Post.
	 */
	protected static function user_can_export_template( \WP_Post $post ): bool {
		if ( ! current_user_can( 'edit_post', $post->ID ) ) {
			return false;
		}
		if ( 'private' === $post->post_status && ! current_user_can( 'read_private_posts', $post->ID ) ) {
			return false;
		}
		if ( 'publish' !== $post->post_status && ! current_user_can( 'edit_post', $post->ID ) ) {
			return false;
		}
		return true;
	}

	/**
	 * Stream Elementor JSON export (admin-ajax GET, same pattern as Elementor “export_template” direct action).
	 */
	public static function ajax_export_template(): void {
		$post_id = isset( $_REQUEST['post'] ) ? absint( wp_unslash( $_REQUEST['post'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended

		if ( ! $post_id || ! check_ajax_referer( 'bdt_tb_export_' . $post_id, '_wpnonce', false ) ) {
			wp_die( esc_html__( 'Security check failed.', 'bdthemes-element-pack' ) );
		}

		if ( get_post_type( $post_id ) !== Meta::POST_TYPE || ! class_exists( '\Elementor\Plugin' ) ) {
			wp_die( esc_html__( 'Invalid export request.', 'bdthemes-element-pack' ) );
		}

		$post = get_post( $post_id );
		if ( ! $post instanceof \WP_Post || ! self::user_can_export_template( $post ) ) {
			wp_die( esc_html__( 'You do not have permission to export this template.', 'bdthemes-element-pack' ) );
		}

		while ( ob_get_level() ) {
			ob_end_clean();
		}

		$export_data = self::build_elementor_template_export_payload( $post );

		$filename = sanitize_file_name( 'elementor-' . $post_id . '-' . gmdate( 'Y-m-d' ) . '.json' );

		nocache_headers();
		header( 'Content-Type: application/json; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . $filename . '"' );

		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON download.
		echo wp_json_encode( $export_data );
		exit;
	}

	/**
	 * Build Elementor library–compatible export array (document API + _elementor_data fallback).
	 *
	 * @param \WP_Post $post Template post.
	 * @return array<string, mixed>
	 */
	protected static function build_elementor_template_export_payload( \WP_Post $post ): array {
		$document = \Elementor\Plugin::instance()->documents->get( $post->ID );

		$content        = [];
		$page_settings  = [];
		$type           = 'page';
		$title          = $post->post_title;

		if ( $document ) {
			$type  = $document->get_name();
			$title = $document->get_main_post()->post_title;
			try {
				$template_data = $document->get_export_data();
				if ( is_array( $template_data ) ) {
					$content       = isset( $template_data['content'] ) ? $template_data['content'] : [];
					$page_settings = isset( $template_data['settings'] ) ? $template_data['settings'] : [];
				}
			} catch ( \Throwable $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
				$content       = [];
				$page_settings = [];
			}
			if ( empty( $page_settings ) && method_exists( $document, 'get_settings' ) ) {
				$page_settings = (array) $document->get_settings();
			}
		}

		if ( empty( $content ) ) {
			$raw = get_post_meta( $post->ID, '_elementor_data', true );
			if ( is_string( $raw ) && $raw !== '' ) {
				$decoded = json_decode( $raw, true );
				if ( is_array( $decoded ) ) {
					$content = $decoded;
				}
			} elseif ( is_array( $raw ) ) {
				$content = $raw;
			}
		}

		$content = apply_filters( 'elementor/template_library/sources/local/export/elements', $content );

		return [
			'content'       => $content,
			'page_settings' => $page_settings,
			'version'       => \Elementor\DB::DB_VERSION,
			'title'         => $title,
			'type'          => $type,
		];
	}

	public static function ajax_rename_template(): void {
		if ( ! wp_verify_nonce( isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '', 'element_pack_builder_nonce' ) ) {
			wp_send_json_error( [ 'message' => 'nonce' ], 403 );
		}

		$id = isset( $_POST['template_id'] ) ? absint( $_POST['template_id'] ) : 0;
		if ( ! $id || get_post_type( $id ) !== Meta::POST_TYPE ) {
			wp_send_json_error( [ 'message' => 'invalid' ], 422 );
		}

		if ( ! current_user_can( 'edit_post', $id ) ) {
			wp_send_json_error( [ 'message' => 'permission' ], 403 );
		}

		$title = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '';
		if ( '' === $title ) {
			wp_send_json_error( [ 'message' => 'title' ], 422 );
		}

		$updated = wp_update_post(
			[
				'ID'         => $id,
				'post_title' => $title,
			],
			true
		);

		if ( is_wp_error( $updated ) ) {
			wp_send_json_error( [ 'message' => $updated->get_error_message() ], 500 );
		}

		wp_send_json_success(
			[
				'template' => self::template_payload( get_post( $id ) ),
			]
		);
	}

	public static function ajax_trash_template(): void {
		if ( ! wp_verify_nonce( isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '', 'element_pack_builder_nonce' ) ) {
			wp_send_json_error( [ 'message' => 'nonce' ], 403 );
		}

		$id = isset( $_POST['template_id'] ) ? absint( $_POST['template_id'] ) : 0;
		if ( ! $id || get_post_type( $id ) !== Meta::POST_TYPE ) {
			wp_send_json_error( [ 'message' => 'invalid' ], 422 );
		}

		if ( ! current_user_can( 'delete_post', $id ) ) {
			wp_send_json_error( [ 'message' => 'permission' ], 403 );
		}

		$trashed = wp_trash_post( $id );
		if ( ! $trashed ) {
			wp_send_json_error( [ 'message' => 'trash' ], 500 );
		}

		wp_send_json_success( [ 'id' => $id ] );
	}

	public static function ajax_save_conditions() {
		if ( ! wp_verify_nonce( isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '', 'element_pack_builder_nonce' ) ) {
			wp_send_json_error( [ 'message' => 'nonce' ], 403 );
		}

		$id = isset( $_POST['template_id'] ) ? absint( $_POST['template_id'] ) : 0;
		if ( ! $id || get_post_type( $id ) !== Meta::POST_TYPE ) {
			wp_send_json_error( [ 'message' => 'invalid' ], 422 );
		}

		if ( ! current_user_can( 'edit_post', $id ) ) {
			wp_send_json_error( [ 'message' => 'permission' ], 403 );
		}

		$type = (string) get_post_meta( $id, Meta::TEMPLATE_TYPE, true );
		if ( '' === $type || ! Builder_Template_Helper::getTemplateByIndex( $type ) ) {
			wp_send_json_error( [ 'message' => 'type' ], 422 );
		}

		$raw  = isset( $_POST['conditions'] ) ? wp_unslash( $_POST['conditions'] ) : '[]';
		$rows = json_decode( $raw, true );
		if ( ! is_array( $rows ) ) {
			wp_send_json_error( [ 'message' => 'rows' ], 422 );
		}

		Template_Conditions::save_rows( $id, $rows );

		wp_send_json_success(
			[
				'template' => self::template_payload( get_post( $id ) ),
			]
		);
	}
}

Theme_Builder_Admin::init();
