<?php

namespace ElementPack\Includes\Builder;

/**
 * Builder Template Helper
 * 
 * Deprecation Schedule:
 * - v9.1.0: Remove 'single' from $pageItem array (deprecated v9.0.2)
 */
class Builder_Template_Helper {

	public static function isTemplateEditMode() {

		if ( get_post_type() == Meta::POST_TYPE ) {
			return true;
		}

		if ( isset( $_REQUEST[ Meta::POST_TYPE ] ) ) {
			return true;
		}
	}

	public static function separator() {
		return '|';
	}

	public static function templates( $single = false ) {

		// Aligned with Elementor Pro Theme Builder: a single Archive template covers
		// all archive variations (Author, Date, Category, Tag, etc.). The runtime
		// "Display Conditions" UI is what differentiates which archive a template
		// applies to.
		$themes_item = [ 
			'header' => esc_html__( 'Header', 'bdthemes-element-pack' ),
			'footer' => esc_html__( 'Footer', 'bdthemes-element-pack' ),
		];
		$postItem    = [ 
			'single'  => esc_html__( 'Single', 'bdthemes-element-pack' ),
			'archive' => esc_html__( 'Archive', 'bdthemes-element-pack' ),
		];
		$pageItem    = [ 
			'single' => esc_html__( 'Single', 'bdthemes-element-pack' ),
			'404'    => esc_html__( 'Error 404', 'bdthemes-element-pack' ),
			'search' => esc_html__( 'Search', 'bdthemes-element-pack' ),
		];
		$shopItem    = [ 
			'shop'      => esc_html__( 'Shop Page', 'bdthemes-element-pack' ),
			'single'    => esc_html__( 'Single Page', 'bdthemes-element-pack' ),
			'cart'      => esc_html__( 'Cart Page', 'bdthemes-element-pack' ),
			'checkout'  => esc_html__( 'Checkout Page', 'bdthemes-element-pack' ),
			'myaccount' => esc_html__( 'My Account Page', 'bdthemes-element-pack' ),
			'orders'    => esc_html__( 'Orders Page', 'bdthemes-element-pack' ),
			'thankyou'  => esc_html__( 'Thank You Page', 'bdthemes-element-pack' ),
		];

		$templates = [ 
			'themes' => $themes_item,
			'post'   => $postItem,
			'page'   => $pageItem,
		];

		// Add product templates only if WooCommerce is active
		if ( class_exists( 'WooCommerce' ) ) {
			$templates['product'] = $shopItem;
		}

		// Automatically add custom post types
		$custom_post_types = get_post_types( [
			'public'   => true,
			'_builtin' => false,
		], 'objects' );

		// Exclude template builder and non-content post types (similar to Elementor's approach)
		$excluded_post_types = [
			'elementor_library',
			'e-floating-buttons', 
			'e-landing-page',
			'attachment',
			'bdt-template-builder',
			'usk-template-builder',
			'upk-template-builder',
			'bdt-custom-template',
			'ep_megamenu_content',
			'product', // Already handled above
			'post',    // Already handled above
			'page',    // Already handled above
			'themes',  // Special case, not a real post type
		];

		foreach ( $custom_post_types as $post_type ) {
			// Skip if already exists or if it's in the excluded list
			if ( isset( $templates[ $post_type->name ] ) || in_array( $post_type->name, $excluded_post_types ) ) {
				continue;
			}

			// Skip post types that don't support editor
			if ( ! post_type_supports( $post_type->name, 'editor' ) ) {
				continue;
			}

			// Skip post types that have no published posts
			$post_count = wp_count_posts( $post_type->name );
			if ( ! $post_count || ( isset( $post_count->publish ) && $post_count->publish == 0 ) ) {
				continue;
			}

			// Skip post types that are not meant for content creation
			if ( ! $post_type->public || ! $post_type->publicly_queryable ) {
				continue;
			}

			// Skip post types that don't support custom fields (often indicates they're not content types)
			if ( ! post_type_supports( $post_type->name, 'custom-fields' ) && ! post_type_supports( $post_type->name, 'title' ) ) {
				continue;
			}

			// Aligned with Elementor Pro: only Single + Archive cards. Taxonomy
			// archives are handled via the Display Conditions UI.
			$templates[ $post_type->name ] = [
				'single'  => esc_html__( 'Single', 'bdthemes-element-pack' ),
				'archive' => esc_html__( 'Archive', 'bdthemes-element-pack' ),
			];
		}

		if ( $single ) {
			$separator = static::separator();
			$return    = [];

			if ( is_array( $templates ) && ! empty( $templates ) ) {

				foreach ( $templates as $keys => $items ) {

					if ( is_array( $items ) ) {

						foreach ( $items as $itemKey => $item ) {
							$return[ "{$keys}{$separator}{$itemKey}" ] = $item;
						}
					}
				}
			}

			return apply_filters(
				'bdthemes_templates_builder_all_templates',
				$return
			);
		}

		return $templates;
	}

	public static function templateForSelectDropdown() {
		return static::templates();
	}

	public static function getTemplateByIndex( $index ) {
		$index     = trim( $index );
		$templates = static::templates( true );

		if ( array_key_exists( $index, $templates ) ) {
			return $templates[ $index ];
		}

		// Backwards compatibility: legacy granular archive types (post|category, post|tag,
		// post|author, post|date and product|archive/category/tag) collapse into the
		// consolidated post|archive / product|shop templates.
		$legacy_alias = static::resolve_legacy_template_index( $index );
		if ( $legacy_alias && array_key_exists( $legacy_alias, $templates ) ) {
			return $templates[ $legacy_alias ];
		}

		return false;
	}

	/**
	 * Map legacy archive template indexes to their consolidated equivalents.
	 *
	 * @param string $index Original template index (e.g. "post|category").
	 * @return string|null Mapped index, or null when no mapping is defined.
	 */
	public static function resolve_legacy_template_index( $index ) {
		$separator = static::separator();
		$legacy    = [
			'post' . $separator . 'category'    => 'post' . $separator . 'archive',
			'post' . $separator . 'tag'         => 'post' . $separator . 'archive',
			'post' . $separator . 'author'      => 'post' . $separator . 'archive',
			'post' . $separator . 'date'        => 'post' . $separator . 'archive',
			'product' . $separator . 'archive'  => 'product' . $separator . 'shop',
			'product' . $separator . 'category' => 'product' . $separator . 'shop',
			'product' . $separator . 'tag'      => 'product' . $separator . 'shop',
		];
		if ( isset( $legacy[ $index ] ) ) {
			return $legacy[ $index ];
		}

		// Custom Post Type taxonomy archives (e.g. "book|genre") collapse to "book|archive".
		$parts = explode( $separator, $index, 2 );
		if ( 2 === count( $parts ) && $parts[1] && taxonomy_exists( $parts[1] ) ) {
			return $parts[0] . $separator . 'archive';
		}

		return null;
	}

	public static function getTemplatePostTypeByIndex( $index ) {
		$index = trim( $index );

		if ( $item = explode( static::separator(), $index ) ) {
			return get_post_type_object( $item[0] );
		}
	}

	public static function is_elementor_active() {
		return did_action( 'elementor/loaded' );
	}

	public static function getTemplate( $slug, $postType = false ) {

		if ( ! $postType ) {
			$postType = get_post_type();
		}
        
		$separator       = static::separator();
		$template        = strtolower( "{$postType}{$separator}{$slug}" );
		$enabledTemplate = strtolower( Meta::TEMPLATE_ID . $template );

		return get_option( $enabledTemplate );
	}

	public static function getTemplateId( $templateType ) {
		$metaIndex = strtolower( Meta::TEMPLATE_ID . $templateType );
		return intval( get_option( $metaIndex ) );
	}

	public static function searchTemplateOptions( $pattern ) {
		global $wpdb;

		$like_pattern = '%' . $wpdb->esc_like( $pattern ) . '%';
		$query        = $wpdb->prepare(
			"SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE %s",
			$like_pattern
		);
		
		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$results = $wpdb->get_results( $query );

		return $results;
	}

	/**
	 * Active (published) template post IDs for a template index, newest first.
	 *
	 * @param string $template_type e.g. post|archive.
	 * @return array<int, int>
	 */
	public static function get_active_template_post_ids( $template_type ) {
		$template_type = strtolower( trim( (string) $template_type ) );
		if ( '' === $template_type ) {
			return [];
		}

		$pattern = strtolower( Meta::TEMPLATE_ID . $template_type . '__' );
		$results = static::searchTemplateOptions( $pattern );
		$ids     = [];

		foreach ( (array) $results as $result ) {
			$post_id = isset( $result->option_value ) ? absint( $result->option_value ) : 0;
			if ( $post_id < 1 || 'publish' !== get_post_status( $post_id ) ) {
				continue;
			}
			$ids[] = $post_id;
		}

		$ids = array_values( array_unique( $ids ) );
		rsort( $ids, SORT_NUMERIC );

		return $ids;
	}

	/**
	 * Resolve the best matching active template for the current request using display conditions.
	 *
	 * @param string       $canonical_type Primary template index (e.g. post|archive).
	 * @param array<int,string> $legacy_types Legacy indexes that should also be considered.
	 * @return int|null Template post ID.
	 */
	public static function resolve_template_for_request( $canonical_type, array $legacy_types = [] ) {
		$candidate_ids = [];

		foreach ( array_merge( [ $canonical_type ], $legacy_types ) as $type ) {
			foreach ( static::get_active_template_post_ids( $type ) as $post_id ) {
				$candidate_ids[ $post_id ] = $post_id;
			}
		}

		if ( empty( $candidate_ids ) ) {
			return null;
		}

		$ids = array_values( $candidate_ids );
		rsort( $ids, SORT_NUMERIC );

		foreach ( $ids as $post_id ) {
			if ( Template_Conditions::template_applies_to_current_request( $post_id ) ) {
				return (int) $post_id;
			}
		}

		return null;
	}

	/**
	 * Resolve a singular Theme Builder template for any public post type.
	 *
	 * Dedicated CPT templates ({post_type}|single) are checked first, then consolidated
	 * post|single templates whose display conditions target the CPT (pt_{slug}) — Elementor Pro style.
	 *
	 * @param string $post_type Post type slug.
	 * @return int|null
	 */
	public static function resolve_singular_template_for_post_type( $post_type ) {
		$post_type = sanitize_key( (string) $post_type );
		if ( '' === $post_type || ! post_type_exists( $post_type ) ) {
			return null;
		}

		$sep = static::separator();

		if ( 'post' === $post_type ) {
			return static::resolve_template_for_request( 'post' . $sep . 'single' );
		}

		if ( 'page' === $post_type ) {
			return static::resolve_template_for_request( 'page' . $sep . 'single' );
		}

		$template = static::resolve_template_for_request( $post_type . $sep . 'single' );
		if ( $template ) {
			return $template;
		}

		return static::resolve_template_for_request( 'post' . $sep . 'single' );
	}

	/**
	 * Resolve an archive Theme Builder template for a custom post type.
	 *
	 * @param string $post_type Post type slug.
	 * @return int|null
	 */
	public static function resolve_archive_template_for_post_type( $post_type ) {
		$post_type = sanitize_key( (string) $post_type );
		if ( '' === $post_type || ! post_type_exists( $post_type ) ) {
			return null;
		}

		$sep = static::separator();

		if ( 'post' === $post_type ) {
			return static::resolve_template_for_request( 'post' . $sep . 'archive' );
		}

		$template = static::resolve_template_for_request( $post_type . $sep . 'archive' );
		if ( $template ) {
			return $template;
		}

		return static::resolve_template_for_request( 'post' . $sep . 'archive' );
	}
}
