<?php
/**
 * Template Library Handler
 * @package Softech_Addons_for_Elementor
 * @since   1.2.0
 * @updated 1.2.3
 */

namespace Softech_Addons_for_Elementor\Includes\Template_Library;

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

class SITS_Template_Library {

	/**
	 * Remote CDN / server URL where the templates folder is hosted.
	 *
	 * @var string
	 */
	private $remote_templates_url = SITS_REMOTE_TEMPLATES_URL;

	/**
	 * Singleton instance.
	 */
	private static $instance = null;

	/**
	 * Cached result of is_remote_mode() — resolved once per request.
	 *
	 * @var bool|null
	 */
	private $use_remote = null;

	/**
	 * In-request cache for the remote manifest.
	 *
	 * @var array|false|null
	 */
	private $remote_manifest = null;

	// =========================================================================
	// Bootstrap
	// =========================================================================

	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {
		add_action( 'wp_ajax_sits_get_template_library', array( $this, 'ajax_get_template_library' ) );
		add_action( 'wp_ajax_sits_insert_template',      array( $this, 'ajax_insert_template' ) );
		add_action( 'admin_enqueue_scripts',             array( $this, 'enqueue_template_library_assets' ) );
	}

	// =========================================================================
	// Auto-detect: local or remote?
	// =========================================================================

	/**
	 * Returns true if the local templates folder is missing (remote mode).
	 * The check is cached for the lifetime of the request.
	 *
	 * @return bool
	 */
	private function is_remote_mode() {
		if ( null === $this->use_remote ) {
			$local_dir        = SITS_ELEMENTOR_ADDONS_PLUGIN_PATH . 'includes/template-library/templates/';
			$this->use_remote = ! is_dir( $local_dir );
		}
		return $this->use_remote;
	}

	/**
	 * Returns the base URL for remote templates (always trailing-slashed).
	 *
	 * @return string
	 */
	private function get_remote_base_url() {
		return trailingslashit( $this->remote_templates_url );
	}

	// =========================================================================
	// Asset enqueueing
	// =========================================================================

	public function enqueue_template_library_assets( $hook ) {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		if ( 'edit.php' !== $hook || ! isset( $_GET['post_type'] ) || 'sits_hf_template' !== sanitize_text_field( wp_unslash( $_GET['post_type'] ) ) ) {
			return;
		}

		wp_enqueue_style(
			'sits-template-library',
			SITS_ELEMENTOR_ADDONS_PLUGIN_URL . 'assets/css/template-library.css',
			array(),
			SITS_ELEMENTOR_ADDONS_VERSION
		);

		wp_enqueue_script(
			'sits-template-library',
			SITS_ELEMENTOR_ADDONS_PLUGIN_URL . 'assets/js/template-library.js',
			array( 'jquery' ),
			SITS_ELEMENTOR_ADDONS_VERSION,
			true
		);

		wp_localize_script(
			'sits-template-library',
			'sitsTemplateLibrary',
			array(
				'ajaxurl'          => admin_url( 'admin-ajax.php' ),
				'nonce'            => wp_create_nonce( 'sits_template_library_nonce' ),
				'editUrlBase'      => admin_url( 'post.php?action=elementor&post=' ),
				'placeholderImage' => SITS_ELEMENTOR_ADDONS_PLUGIN_URL . 'assets/images/placeholder-image.webp',
				'strings'          => array(
					'loadingTemplates' => esc_html__( 'Loading templates...', 'softech-addons-for-elementor' ),
					'errorLoading'     => esc_html__( 'Error loading templates. Please try again.', 'softech-addons-for-elementor' ),
					'selectTemplate'   => esc_html__( 'Choose Template', 'softech-addons-for-elementor' ),
					'header'           => esc_html__( 'Header', 'softech-addons-for-elementor' ),
					'footer'           => esc_html__( 'Footer', 'softech-addons-for-elementor' ),
					'skip'             => esc_html__( 'Skip — Start Blank', 'softech-addons-for-elementor' ),
					'createAndEdit'    => esc_html__( 'Insert &amp; Edit with Elementor', 'softech-addons-for-elementor' ),
					'inserting'        => esc_html__( 'Inserting template...', 'softech-addons-for-elementor' ),
					'errorInserting'   => esc_html__( 'Error inserting template. Please try again.', 'softech-addons-for-elementor' ),
				),
			)
		);
	}

	// =========================================================================
	// AJAX — get template list
	// =========================================================================

	public function ajax_get_template_library() {
		check_ajax_referer( 'sits_template_library_nonce', 'nonce' );

		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Permission denied.', 'softech-addons-for-elementor' ) ) );
			return;
		}

		$type      = isset( $_POST['template_type'] ) ? sanitize_text_field( wp_unslash( $_POST['template_type'] ) ) : '';
		$all_types = array( 'header', 'footer', 'archive', 'single_page', 'single_post', '404_page' );

		if ( ! in_array( $type, $all_types, true ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Invalid template type.', 'softech-addons-for-elementor' ) ) );
			return;
		}

		$supported_types = array( 'header', 'footer', '404_page' );
		if ( ! in_array( $type, $supported_types, true ) ) {
			wp_send_json_success( array( 'templates' => array(), 'show_empty_state' => true ) );
			return;
		}

		$templates = $this->get_templates_by_type( $type );

		wp_send_json_success( array(
			'templates'        => $templates,
			'show_empty_state' => empty( $templates ),
		) );
	}

	// =========================================================================
	// AJAX — insert template
	// =========================================================================

	public function ajax_insert_template() {
		check_ajax_referer( 'sits_template_library_nonce', 'nonce' );

		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Permission denied.', 'softech-addons-for-elementor' ) ) );
		}

		$post_id     = isset( $_POST['post_id'] )       ? absint( wp_unslash( $_POST['post_id'] ) )                     : 0;
		$template_id = isset( $_POST['template_id'] )   ? sanitize_text_field( wp_unslash( $_POST['template_id'] ) )    : '';
		$type        = isset( $_POST['template_type'] )  ? sanitize_text_field( wp_unslash( $_POST['template_type'] ) ) : '';

		$all_types = array( 'header', 'footer', 'archive', 'single_page', 'single_post', '404_page' );
		if ( ! $post_id || ! $template_id || ! in_array( $type, $all_types, true ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Invalid request.', 'softech-addons-for-elementor' ) ) );
		}

		$post = get_post( $post_id );
		if ( ! $post || 'sits_hf_template' !== $post->post_type || ! current_user_can( 'edit_post', $post_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Invalid post.', 'softech-addons-for-elementor' ) ) );
		}

		// Restrict to safe characters — no path traversal possible.
		if ( ! preg_match( '/^[a-z0-9_\-]+$/', $template_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Invalid template identifier.', 'softech-addons-for-elementor' ) ) );
		}

		$template_data = $this->load_template( $type, $template_id );

		if ( ! $template_data || ! isset( $template_data['content'] ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Template not found or invalid.', 'softech-addons-for-elementor' ) ) );
		}

		$result = $this->insert_elementor_data( $post_id, $template_data['content'] );

		if ( $result ) {
			wp_send_json_success( array(
				'message'       => esc_html__( 'Template inserted successfully!', 'softech-addons-for-elementor' ),
				'elementor_url' => admin_url( 'post.php?post=' . $post_id . '&action=elementor' ),
			) );
		} else {
			wp_send_json_error( array( 'message' => esc_html__( 'Failed to insert template.', 'softech-addons-for-elementor' ) ) );
		}
	}

	// =========================================================================
	// Unified dispatcher
	// =========================================================================

	/**
	 * Get all templates for a type — auto-routes to local or remote.
	 */
	private function get_templates_by_type( $type ) {
		return $this->is_remote_mode()
			? $this->get_remote_templates_by_type( $type )
			: $this->get_local_templates_by_type( $type );
	}

	/**
	 * Load a single template by type + ID — auto-routes to local or remote.
	 */
	private function load_template( $type, $template_id ) {
		if ( $this->is_remote_mode() ) {
			$url = $this->get_remote_base_url() . $type . '/' . $template_id . '.json';
			return $this->load_remote_template( $url );
		}

		$file = SITS_ELEMENTOR_ADDONS_PLUGIN_PATH . 'includes/template-library/templates/' . $type . '/' . $template_id . '.json';
		return $this->load_local_template( $file );
	}

	// =========================================================================
	// LOCAL loader
	// =========================================================================

	private function get_local_templates_by_type( $type ) {
		$dir   = SITS_ELEMENTOR_ADDONS_PLUGIN_PATH . 'includes/template-library/templates/' . $type . '/';
		$files = is_dir( $dir ) ? glob( $dir . '*.json' ) : array();

		if ( ! $files ) {
			return array();
		}

		$templates = array();
		foreach ( $files as $file ) {
			$data = $this->load_local_template( $file );
			if ( $data ) {
				$templates[] = $data;
			}
		}

		return $templates;
	}

	private function load_local_template( $file ) {
		if ( ! file_exists( $file ) ) {
			return false;
		}

		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- local plugin file.
		$data = json_decode( file_get_contents( $file ), true );

		if ( ! is_array( $data ) || ! isset( $data['title'] ) ) {
			return false;
		}

		$data['template_id'] = basename( $file, '.json' );

		if ( isset( $data['thumbnail'] ) ) {
			$data['thumbnail'] = SITS_ELEMENTOR_ADDONS_PLUGIN_URL . 'includes/template-library/templates/' . $data['thumbnail'];
		}

		return $data;
	}

	// =========================================================================
	// REMOTE loader
	// =========================================================================

	/**
	 * Fetch all templates for a type from the remote server.
	 * Uses manifest.json to discover template IDs (can't glob a remote dir).
	 */
	private function get_remote_templates_by_type( $type ) {
		$manifest = $this->get_remote_manifest();

		if ( ! $manifest || empty( $manifest[ $type ] ) || ! is_array( $manifest[ $type ] ) ) {
			return array();
		}

		$templates = array();

		foreach ( $manifest[ $type ] as $template_id ) {
			$template_id = sanitize_key( $template_id );
			if ( ! $template_id ) {
				continue;
			}

			$url  = $this->get_remote_base_url() . $type . '/' . $template_id . '.json';
			$data = $this->load_remote_template( $url );

			if ( $data ) {
				$templates[] = $data;
			}
		}

		return $templates;
	}

	/**
	 * Fetch manifest.json from the remote server (cached per-request and via transient).
	 *
	 * Timeout is intentionally set lower than the per-template fetch (8 s vs 12 s)
	 * because the manifest is a tiny JSON index — if it cannot be retrieved quickly
	 * the remote server is likely unavailable and we fall back to the transient cache.
	 *
	 * manifest.json format:
	 * {
	 *   "header":      ["header-red-minimal", "header-green-modern"],
	 *   "footer":      ["footer-teal-corporate"],
	 *   "single_post": ["post-editorial-dark"],
	 *   "404_page":    ["404-minimal-teal"]
	 * }
	 */
	private function get_remote_manifest() {
	     if ( empty( $this->remote_templates_url ) ) {
        return false;
    }
		// Per-request in-memory cache — avoids duplicate HTTP calls within the same page load.
		if ( null !== $this->remote_manifest ) {
			return $this->remote_manifest;
		}

		// Load the last known-good manifest from the transient cache.
		// This is used as a fallback if the remote server is unreachable.
		$cached = get_transient( 'sits_remote_manifest' );

		$response = wp_remote_get( $this->get_remote_base_url() . 'manifest.json', array(
			'timeout'    => 8,  // manifest is tiny; fail fast so the admin UI doesn't hang
			'user-agent' => 'SoftechAddons/' . SITS_ELEMENTOR_ADDONS_VERSION,
		) );

		if ( is_wp_error( $response ) ) {
			// Remote is unreachable — serve the stale cached manifest so the
			// Template Library still shows previously-discovered templates.
			$this->remote_manifest = $cached ?: false;
			return $this->remote_manifest;
		}

		if ( 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
			// Non-200 from the server (e.g. 503) — same fallback strategy.
			$this->remote_manifest = $cached ?: false;
			return $this->remote_manifest;
		}

		$data                  = json_decode( wp_remote_retrieve_body( $response ), true );
		$this->remote_manifest = is_array( $data ) ? $data : false;

		// Persist a fresh manifest for 24 hours so it survives the next request.
		if ( $this->remote_manifest ) {
			set_transient( 'sits_remote_manifest', $this->remote_manifest, 24 * HOUR_IN_SECONDS );
		}

		return $this->remote_manifest;
	}

	/**
	 * Fetch and validate a single remote template JSON.
	 */
	private function load_remote_template( $url ) {
		$response = wp_remote_get( $url, array(
			'timeout'    => 12,  // templates are larger than the manifest but still bounded
			'user-agent' => 'SoftechAddons/' . SITS_ELEMENTOR_ADDONS_VERSION,
		) );

		if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
			return false;
		}

		$data = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( ! is_array( $data ) || ! isset( $data['title'] ) ) {
			return false;
		}

		$data['template_id'] = basename( $url, '.json' );

		if ( isset( $data['thumbnail'] ) ) {
			// thumbnail value in JSON is a relative path e.g. "header/header-red-minimal.png"
			$data['thumbnail'] = $this->get_remote_base_url() . $data['thumbnail'];
		}

		return $data;
	}

	// =========================================================================
	// Elementor data insertion
	// =========================================================================

	private function insert_elementor_data( $post_id, $content ) {
		$content = $this->inject_primary_menu( $content );

		update_post_meta( $post_id, '_elementor_data',          wp_json_encode( $content ) );
		update_post_meta( $post_id, '_elementor_edit_mode',     'builder' );
		update_post_meta( $post_id, '_elementor_template_type', 'sits-hf-template' );
		update_post_meta( $post_id, '_wp_page_template',        'elementor_canvas' );
		update_post_meta( $post_id, '_elementor_version',       ELEMENTOR_VERSION );

		if ( class_exists( '\Elementor\Plugin' ) ) {
			\Elementor\Plugin::$instance->files_manager->clear_cache();
		}

		return true;
	}

	private function inject_primary_menu( $elements ) {
		static $primary_id = null;

		if ( null === $primary_id ) {
			$primary_id = $this->get_primary_menu_id();
		}

		if ( ! $primary_id ) {
			return $elements;
		}

		foreach ( $elements as &$el ) {
			if (
				isset( $el['widgetType'] ) &&
				'sitsel_mega_menu_widget' === $el['widgetType'] &&
				isset( $el['settings']['menu_select'] ) &&
				'' === (string) $el['settings']['menu_select']
			) {
				$el['settings']['menu_select'] = (string) $primary_id;
			}

			if ( ! empty( $el['elements'] ) && is_array( $el['elements'] ) ) {
				$el['elements'] = $this->inject_primary_menu( $el['elements'] );
			}
		}
		unset( $el );

		return $elements;
	}

	private function get_primary_menu_id() {
		$locations = get_nav_menu_locations();
		$preferred = array( 'primary', 'main-menu', 'main_menu', 'header', 'header-menu', 'header_menu' );

		foreach ( $preferred as $loc ) {
			if ( ! empty( $locations[ $loc ] ) ) {
				$menu = wp_get_nav_menu_object( $locations[ $loc ] );
				if ( $menu && ! is_wp_error( $menu ) ) {
					return (int) $menu->term_id;
				}
			}
		}

		foreach ( $locations as $mid ) {
			if ( $mid ) {
				$menu = wp_get_nav_menu_object( $mid );
				if ( $menu && ! is_wp_error( $menu ) ) {
					return (int) $menu->term_id;
				}
			}
		}

		$menus = wp_get_nav_menus();
		return ! empty( $menus ) ? (int) $menus[0]->term_id : false;
	}
}

SITS_Template_Library::instance();
