<?php
defined( 'ABSPATH' ) || exit;

/**
 * Loads and applies bundled TukiFlow landing page templates.
 */
class TFDC_Template_Library {

	const MANIFEST_FILE = 'templates/manifest.json';
	const META_ID       = '_tfdc_template_id';
	const META_BUILDER  = '_tfdc_template_builder';

	/**
	 * Return available templates from the plugin manifest.
	 *
	 * @return array
	 */
	public static function get_templates() {
		$templates = array(
			self::get_blank_template(),
		);

		$manifest = self::read_manifest();
		foreach ( $manifest as $raw_template ) {
			$template = self::normalize_template( $raw_template );
			if ( $template ) {
				$templates[] = $template;
			}
		}

		return $templates;
	}

	/**
	 * Apply a selected template to a newly-created page.
	 *
	 * @param int    $page_id     Page ID.
	 * @param string $template_id Template ID.
	 * @param int[]  $product_ids Product IDs.
	 * @return true|WP_Error
	 */
	public static function apply_template( $page_id, $template_id, $product_ids ) {
		$page_id     = absint( $page_id );
		$template_id = sanitize_key( $template_id );
		$shortcode   = self::build_checkout_shortcode( $product_ids );

		if ( ! $page_id ) {
			return new WP_Error( 'tfdc_template_error', __( 'Invalid landing page.', 'tukiflow-direct-checkout-woocommerce' ) );
		}

		if ( ! $template_id || 'blank' === $template_id ) {
			return self::apply_blank_template( $page_id, $shortcode, $product_ids );
		}

		$template = self::get_template( $template_id );
		if ( is_wp_error( $template ) ) {
			return $template;
		}

		if ( 'elementor' === $template['builder'] ) {
			return self::apply_elementor_template( $page_id, $template, $shortcode );
		}

		return self::apply_gutenberg_template( $page_id, $template, $shortcode );
	}

	/**
	 * Build the checkout shortcode for one or more selected products.
	 *
	 * @param int[] $product_ids Product IDs.
	 * @return string
	 */
	public static function build_checkout_shortcode( $product_ids ) {
		$product_ids = array_values( array_filter( array_map( 'absint', $product_ids ) ) );

		if ( 1 === count( $product_ids ) ) {
			return sprintf( '[tukiflow product_id="%d"]', $product_ids[0] );
		}

		return sprintf( '[tukiflow product_ids="%s"]', implode( ',', $product_ids ) );
	}

	/**
	 * Get a single template by ID.
	 *
	 * @param string $template_id Template ID.
	 * @return array|WP_Error
	 */
	private static function get_template( $template_id ) {
		foreach ( self::get_templates() as $template ) {
			if ( $template_id === $template['id'] ) {
				if ( ! $template['available'] ) {
					return new WP_Error( 'tfdc_template_missing', __( 'The selected template file is missing.', 'tukiflow-direct-checkout-woocommerce' ) );
				}

				return $template;
			}
		}

		return new WP_Error( 'tfdc_template_missing', __( 'The selected template could not be found.', 'tukiflow-direct-checkout-woocommerce' ) );
	}

	/**
	 * Apply the default blank shortcode page.
	 *
	 * @param int    $page_id     Page ID.
	 * @param string $shortcode   Checkout shortcode.
	 * @param int[]  $product_ids Product IDs.
	 * @return true|WP_Error
	 */
	private static function apply_blank_template( $page_id, $shortcode, $product_ids ) {
		$content = self::build_blank_template_content( $product_ids, $shortcode );

		$updated = wp_update_post(
			array(
				'ID'           => $page_id,
				'post_content' => $content,
			),
			true
		);

		if ( is_wp_error( $updated ) ) {
			return $updated;
		}

		update_post_meta( $page_id, self::META_ID, 'blank' );
		update_post_meta( $page_id, self::META_BUILDER, 'shortcode' );

		return true;
	}

	/**
	 * Build the default blank-template content.
	 *
	 * For single-product pages, prefill the block editor with the product title,
	 * product description, and checkout shortcode. Multi-product pages keep the
	 * original shortcode-only behavior for now.
	 *
	 * @param int[]  $product_ids Product IDs.
	 * @param string $shortcode   Checkout shortcode.
	 * @return string
	 */
	private static function build_blank_template_content( $product_ids, $shortcode ) {
		$product_ids = array_values( array_filter( array_map( 'absint', $product_ids ) ) );

		if ( 1 !== count( $product_ids ) ) {
			return $shortcode;
		}

		$product = wc_get_product( $product_ids[0] );
		if ( ! $product ) {
			return $shortcode;
		}

		$blocks = array();
		$title  = wp_strip_all_tags( $product->get_name() );

		if ( '' !== $title ) {
			$blocks[] = "<!-- wp:heading -->\n<h2>" . esc_html( $title ) . "</h2>\n<!-- /wp:heading -->";
		}

		$description = $product->get_short_description();
		if ( '' === trim( wp_strip_all_tags( $description ) ) ) {
			$description = $product->get_description();
		}

		$description = trim( (string) $description );
		if ( '' !== $description ) {
			$blocks[] = '<!-- wp:paragraph -->' . "\n" . wpautop( wp_kses_post( $description ) ) . "\n<!-- /wp:paragraph -->";
		}

		$blocks[] = "<!-- wp:shortcode -->\n" . $shortcode . "\n<!-- /wp:shortcode -->";

		return implode( "\n\n", $blocks );
	}

	/**
	 * Apply a Gutenberg block markup template.
	 *
	 * @param int    $page_id   Page ID.
	 * @param array  $template  Template data.
	 * @param string $shortcode Checkout shortcode.
	 * @return true|WP_Error
	 */
	private static function apply_gutenberg_template( $page_id, $template, $shortcode ) {
		$content = self::read_template_file( $template );
		if ( is_wp_error( $content ) ) {
			return $content;
		}

		$has_shortcode = self::contains_tukiflow_shortcode( $content );
		$content       = self::replace_tukiflow_shortcodes( $content, $shortcode );

		if ( ! $has_shortcode ) {
			$content .= "\n\n<!-- wp:shortcode -->\n" . $shortcode . "\n<!-- /wp:shortcode -->";
		}

		$updated = wp_update_post(
			array(
				'ID'           => $page_id,
				'post_content' => $content,
			),
			true
		);

		if ( is_wp_error( $updated ) ) {
			return $updated;
		}

		update_post_meta( $page_id, self::META_ID, $template['id'] );
		update_post_meta( $page_id, self::META_BUILDER, 'gutenberg' );

		return true;
	}

	/**
	 * Apply an exported Elementor JSON template.
	 *
	 * @param int    $page_id   Page ID.
	 * @param array  $template  Template data.
	 * @param string $shortcode Checkout shortcode.
	 * @return true|WP_Error
	 */
	private static function apply_elementor_template( $page_id, $template, $shortcode ) {
		if ( ! defined( 'ELEMENTOR_VERSION' ) ) {
			return new WP_Error( 'tfdc_elementor_missing', __( 'Elementor must be active to import an Elementor template.', 'tukiflow-direct-checkout-woocommerce' ) );
		}

		$json = self::read_template_file( $template );
		if ( is_wp_error( $json ) ) {
			return $json;
		}

		$data = json_decode( $json, true );
		if ( ! is_array( $data ) ) {
			return new WP_Error( 'tfdc_elementor_invalid', __( 'The selected Elementor template JSON is invalid.', 'tukiflow-direct-checkout-woocommerce' ) );
		}

		$content = isset( $data['content'] ) && is_array( $data['content'] ) ? $data['content'] : $data;
		if ( ! self::contains_tukiflow_shortcode( $content ) ) {
			return new WP_Error( 'tfdc_elementor_shortcode_missing', __( 'Elementor templates must include a Shortcode widget containing [tukiflow].', 'tukiflow-direct-checkout-woocommerce' ) );
		}

		$content       = self::replace_tukiflow_shortcodes( $content, $shortcode );
		$page_settings = isset( $data['page_settings'] ) && is_array( $data['page_settings'] ) ? $data['page_settings'] : array();
		$page_settings = self::replace_tukiflow_shortcodes( $page_settings, $shortcode );

		$updated = wp_update_post(
			array(
				'ID'           => $page_id,
				'post_content' => $shortcode,
			),
			true
		);

		if ( is_wp_error( $updated ) ) {
			return $updated;
		}

		update_post_meta( $page_id, '_elementor_edit_mode', 'builder' );
		update_post_meta( $page_id, '_elementor_template_type', 'wp-page' );
		update_post_meta( $page_id, '_elementor_version', ELEMENTOR_VERSION );
		update_post_meta( $page_id, '_elementor_data', wp_slash( wp_json_encode( $content ) ) );
		update_post_meta( $page_id, '_elementor_page_settings', $page_settings );
		delete_post_meta( $page_id, '_elementor_css' );

		if ( ! empty( $template['page_template'] ) ) {
			update_post_meta( $page_id, '_wp_page_template', sanitize_text_field( $template['page_template'] ) );
		}

		update_post_meta( $page_id, self::META_ID, $template['id'] );
		update_post_meta( $page_id, self::META_BUILDER, 'elementor' );

		return true;
	}

	/**
	 * Replace any [tukiflow ...] shortcode in a string or nested array.
	 *
	 * @param mixed  $value     Value to inspect.
	 * @param string $shortcode Replacement shortcode.
	 * @return mixed
	 */
	private static function replace_tukiflow_shortcodes( $value, $shortcode ) {
		if ( is_array( $value ) ) {
			foreach ( $value as $key => $item ) {
				$value[ $key ] = self::replace_tukiflow_shortcodes( $item, $shortcode );
			}

			return $value;
		}

		if ( ! is_string( $value ) || ! self::contains_tukiflow_shortcode( $value ) ) {
			return $value;
		}

		$pattern = get_shortcode_regex( array( 'tukiflow' ) );

		return preg_replace_callback(
			'/' . $pattern . '/s',
			function ( $matches ) use ( $shortcode ) {
				return 'tukiflow' === $matches[2] ? $shortcode : $matches[0];
			},
			$value
		);
	}

	/**
	 * Check whether a string or nested array contains the TukiFlow shortcode.
	 *
	 * @param mixed $value Value to inspect.
	 * @return bool
	 */
	private static function contains_tukiflow_shortcode( $value ) {
		if ( is_array( $value ) ) {
			foreach ( $value as $item ) {
				if ( self::contains_tukiflow_shortcode( $item ) ) {
					return true;
				}
			}

			return false;
		}

		if ( ! is_string( $value ) || false === strpos( $value, '[tukiflow' ) ) {
			return false;
		}

		$pattern = get_shortcode_regex( array( 'tukiflow' ) );

		return 1 === preg_match( '/' . $pattern . '/s', $value );
	}

	/**
	 * Read and decode the template manifest.
	 *
	 * @return array
	 */
	private static function read_manifest() {
		$path = TFDC_DIR . self::MANIFEST_FILE;
		if ( ! file_exists( $path ) ) {
			return array();
		}

		$contents = file_get_contents( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
		$decoded  = json_decode( $contents, true );

		if ( isset( $decoded['templates'] ) && is_array( $decoded['templates'] ) ) {
			return $decoded['templates'];
		}

		return is_array( $decoded ) ? $decoded : array();
	}

	/**
	 * Normalize a manifest row for API/UI consumption.
	 *
	 * @param array $raw_template Raw template data.
	 * @return array|null
	 */
	private static function normalize_template( $raw_template ) {
		if ( ! is_array( $raw_template ) ) {
			return null;
		}

		$id      = isset( $raw_template['id'] ) ? sanitize_key( $raw_template['id'] ) : '';
		$name    = isset( $raw_template['name'] ) ? sanitize_text_field( $raw_template['name'] ) : '';
		$builder = isset( $raw_template['builder'] ) ? sanitize_key( $raw_template['builder'] ) : 'gutenberg';
		$source  = isset( $raw_template['source'] ) ? self::sanitize_relative_path( $raw_template['source'] ) : '';

		if ( ! $id || ! $name || ! $source || ! in_array( $builder, array( 'gutenberg', 'elementor' ), true ) ) {
			return null;
		}

		$thumbnail   = isset( $raw_template['thumbnail'] ) ? self::sanitize_relative_path( $raw_template['thumbnail'] ) : '';
		$preview_url = isset( $raw_template['preview_url'] ) ? esc_url_raw( $raw_template['preview_url'] ) : '';

		return array(
			'id'            => $id,
			'name'          => $name,
			'description'   => isset( $raw_template['description'] ) ? sanitize_text_field( $raw_template['description'] ) : '',
			'builder'       => $builder,
			'source'        => $source,
			'thumbnail'     => $thumbnail ? TFDC_URL . 'templates/' . $thumbnail : '',
			'preview_url'   => $preview_url,
			'page_template' => isset( $raw_template['page_template'] ) ? sanitize_text_field( $raw_template['page_template'] ) : '',
			'available'     => file_exists( TFDC_DIR . 'templates/' . $source ),
		);
	}

	/**
	 * Read a template source file.
	 *
	 * @param array $template Template data.
	 * @return string|WP_Error
	 */
	private static function read_template_file( $template ) {
		$path = TFDC_DIR . 'templates/' . $template['source'];
		if ( ! file_exists( $path ) ) {
			return new WP_Error( 'tfdc_template_missing', __( 'The selected template file is missing.', 'tukiflow-direct-checkout-woocommerce' ) );
		}

		return file_get_contents( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
	}

	/**
	 * Prevent manifest paths from escaping the templates directory.
	 *
	 * @param string $path Relative path.
	 * @return string
	 */
	private static function sanitize_relative_path( $path ) {
		$path = str_replace( '\\', '/', sanitize_text_field( $path ) );
		$path = ltrim( $path, '/' );

		if ( false !== strpos( $path, '..' ) ) {
			return '';
		}

		return $path;
	}

	/**
	 * Default no-template option.
	 *
	 * @return array
	 */
	private static function get_blank_template() {
		return array(
			'id'          => 'blank',
			'name'        => __( 'Blank Checkout Page', 'tukiflow-direct-checkout-woocommerce' ),
			'description' => __( 'Create a simple draft page that only contains the TukiFlow checkout shortcode.', 'tukiflow-direct-checkout-woocommerce' ),
			'builder'     => 'shortcode',
			'source'      => '',
			'thumbnail'   => '',
			'available'   => true,
		);
	}
}
