<?php
/**
 * OpenGraph Meta Tags Handler
 *
 * Outputs OpenGraph meta tags for product pages when enabled.
 *
 * @package GGM_Commerce
 */

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

/**
 * Class GGM_Commerce_OpenGraph
 *
 * Handles OpenGraph meta tag output for product pages.
 */
class GGM_Commerce_OpenGraph {

	/**
	 * Initialize the OpenGraph handler.
	 */
	public static function init() {
		// Only proceed if OpenGraph is enabled.
		if ( ! self::is_enabled() ) {
			return;
		}

		// Hook into wp_head to output meta tags.
		add_action( 'wp_head', array( __CLASS__, 'output_meta_tags' ), 5 );
	}

	/**
	 * Check if OpenGraph output is enabled.
	 *
	 * @return bool
	 */
	public static function is_enabled() {
		return (bool) get_option( 'ggm_commerce_opengraph_enabled', 0 );
	}

	/**
	 * Output OpenGraph meta tags.
	 */
	public static function output_meta_tags() {
		// Check if we're on a product details page.
		$product = self::get_current_product();

		if ( $product ) {
			self::output_product_tags( $product );
			return;
		}

		// Check if we're on a category archive page.
		$category = self::get_current_category();

		if ( $category ) {
			self::output_category_tags( $category );
			return;
		}

		// Check if we're on a tag archive page.
		$tag = self::get_current_tag();

		if ( $tag ) {
			self::output_tag_tags( $tag );
			return;
		}

		// Check if we're on the shop page.
		if ( self::is_shop_page() ) {
			self::output_shop_tags();
			return;
		}
	}

	/**
	 * Get the current product if on a product details page.
	 *
	 * @return object|null Product object or null.
	 */
	private static function get_current_product() {
		global $wpdb;

		$product_details_page_id = get_option( 'ggm_commerce_product_details_page_id' );

		if ( ! $product_details_page_id || ! is_page( $product_details_page_id ) ) {
			return null;
		}

		// First check the global variable set by the request parser (most reliable).
		if ( ! empty( $GLOBALS['ggmc_current_product_id'] ) ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			return $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}ggmc_products WHERE id = %d AND status = 'active'",
					(int) $GLOBALS['ggmc_current_product_id']
				)
			);
		}

		// Fallback: Try to get product from query var.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameter for display.
		$product_slug = get_query_var( 'ggmc_product_slug' );
		if ( ! empty( $product_slug ) ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			return $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}ggmc_products WHERE slug = %s AND status = 'active'",
					$product_slug
				)
			);
		}

		// Fallback: Try to get product from URL path directly.
		$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
		$page        = get_post( $product_details_page_id );

		if ( $page && ! empty( $request_uri ) ) {
			$page_slug = $page->post_name;
			// Remove query string.
			if ( ( $pos = strpos( $request_uri, '?' ) ) !== false ) {
				$request_uri = substr( $request_uri, 0, $pos );
			}
			$request_uri = trim( $request_uri, '/' );

			// Match pattern: {page-slug}/{product-slug}.
			$pattern = '#^(?:.*/)?(' . preg_quote( $page_slug, '#' ) . ')/([^/]+)/?$#i';
			if ( preg_match( $pattern, $request_uri, $matches ) ) {
				$product_slug = sanitize_title( $matches[2] );
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				return $wpdb->get_row(
					$wpdb->prepare(
						"SELECT * FROM {$wpdb->prefix}ggmc_products WHERE slug = %s AND status = 'active'",
						$product_slug
					)
				);
			}
		}

		// Fallback: Check for ID parameter.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameter for display.
		$product_id = isset( $_GET['id'] ) ? absint( $_GET['id'] ) : 0;
		if ( $product_id ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			return $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}ggmc_products WHERE id = %d AND status = 'active'",
					$product_id
				)
			);
		}

		return null;
	}

	/**
	 * Get the current category if on a category archive page.
	 *
	 * @return object|null Category object or null.
	 */
	private static function get_current_category() {
		global $wpdb;

		$category_page_id = get_option( 'ggm_commerce_category_archive_page_id' );

		if ( ! $category_page_id || ! is_page( $category_page_id ) ) {
			return null;
		}

		// First check the global variable set by the request parser.
		if ( ! empty( $GLOBALS['ggmc_current_category_id'] ) ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			return $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}ggmc_categories WHERE id = %d",
					(int) $GLOBALS['ggmc_current_category_id']
				)
			);
		}

		// Fallback: Try to get category from query var.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameter for display.
		$category_slug = get_query_var( 'ggmc_category_slug' );
		if ( ! empty( $category_slug ) ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			return $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}ggmc_categories WHERE slug = %s",
					$category_slug
				)
			);
		}

		// Fallback: Try to get category from URL path directly.
		$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
		$page        = get_post( $category_page_id );

		if ( $page && ! empty( $request_uri ) ) {
			$page_slug = $page->post_name;
			// Remove query string.
			if ( ( $pos = strpos( $request_uri, '?' ) ) !== false ) {
				$request_uri = substr( $request_uri, 0, $pos );
			}
			$request_uri = trim( $request_uri, '/' );

			// Match pattern: {page-slug}/{category-slug}.
			$pattern = '#^(?:.*/)?(' . preg_quote( $page_slug, '#' ) . ')/([^/]+)/?$#i';
			if ( preg_match( $pattern, $request_uri, $matches ) ) {
				$category_slug = sanitize_title( $matches[2] );
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				return $wpdb->get_row(
					$wpdb->prepare(
						"SELECT * FROM {$wpdb->prefix}ggmc_categories WHERE slug = %s",
						$category_slug
					)
				);
			}
		}

		return null;
	}

	/**
	 * Get the current tag if on a tag archive page.
	 *
	 * @return object|null Tag object or null.
	 */
	private static function get_current_tag() {
		global $wpdb;

		$tag_page_id = get_option( 'ggm_commerce_tag_archive_page_id' );

		if ( ! $tag_page_id || ! is_page( $tag_page_id ) ) {
			return null;
		}

		// First check the global variable set by the request parser.
		if ( ! empty( $GLOBALS['ggmc_current_tag_id'] ) ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			return $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}ggmc_tags WHERE id = %d",
					(int) $GLOBALS['ggmc_current_tag_id']
				)
			);
		}

		// Fallback: Try to get tag from query var.
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading URL parameter for display.
		$tag_slug = get_query_var( 'ggmc_tag_slug' );
		if ( ! empty( $tag_slug ) ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			return $wpdb->get_row(
				$wpdb->prepare(
					"SELECT * FROM {$wpdb->prefix}ggmc_tags WHERE slug = %s",
					$tag_slug
				)
			);
		}

		// Fallback: Try to get tag from URL path directly.
		$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
		$page        = get_post( $tag_page_id );

		if ( $page && ! empty( $request_uri ) ) {
			$page_slug = $page->post_name;
			// Remove query string.
			if ( ( $pos = strpos( $request_uri, '?' ) ) !== false ) {
				$request_uri = substr( $request_uri, 0, $pos );
			}
			$request_uri = trim( $request_uri, '/' );

			// Match pattern: {page-slug}/{tag-slug}.
			$pattern = '#^(?:.*/)?(' . preg_quote( $page_slug, '#' ) . ')/([^/]+)/?$#i';
			if ( preg_match( $pattern, $request_uri, $matches ) ) {
				$tag_slug = sanitize_title( $matches[2] );
				// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
				return $wpdb->get_row(
					$wpdb->prepare(
						"SELECT * FROM {$wpdb->prefix}ggmc_tags WHERE slug = %s",
						$tag_slug
					)
				);
			}
		}

		return null;
	}

	/**
	 * Check if we're on the shop page.
	 *
	 * @return bool
	 */
	private static function is_shop_page() {
		$shop_page_id = get_option( 'ggm_commerce_shop_page_id' );
		return $shop_page_id && is_page( $shop_page_id );
	}

	/**
	 * Output OpenGraph tags for a product.
	 *
	 * @param object $product Product object.
	 */
	private static function output_product_tags( $product ) {
		$title       = $product->name;
		$description = ! empty( $product->description ) ? wp_strip_all_tags( $product->description ) : '';
		$url         = self::get_product_url( $product );

		// Get image URL from attachment ID.
		$image = '';
		if ( ! empty( $product->image_id ) ) {
			$image = wp_get_attachment_url( $product->image_id );
		}

		// Truncate description to 200 characters.
		if ( strlen( $description ) > 200 ) {
			$description = substr( $description, 0, 197 ) . '...';
		}

		echo "\n<!-- GGM Commerce OpenGraph Tags -->\n";
		echo '<meta property="og:type" content="product" />' . "\n";
		echo '<meta property="og:title" content="' . esc_attr( $title ) . '" />' . "\n";

		if ( $description ) {
			echo '<meta property="og:description" content="' . esc_attr( $description ) . '" />' . "\n";
			echo '<meta name="description" content="' . esc_attr( $description ) . '" />' . "\n";
		}

		echo '<meta property="og:url" content="' . esc_url( $url ) . '" />' . "\n";

		if ( $image ) {
			echo '<meta property="og:image" content="' . esc_url( $image ) . '" />' . "\n";
		}

		// Add product-specific tags.
		if ( ! empty( $product->price ) ) {
			$currency = self::get_currency_code();
			echo '<meta property="product:price:amount" content="' . esc_attr( $product->price ) . '" />' . "\n";
			echo '<meta property="product:price:currency" content="' . esc_attr( $currency ) . '" />' . "\n";
		}

		// Add site name.
		echo '<meta property="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '" />' . "\n";
		echo "<!-- /GGM Commerce OpenGraph Tags -->\n\n";
	}

	/**
	 * Output OpenGraph tags for a category archive.
	 *
	 * @param object $category Category object.
	 */
	private static function output_category_tags( $category ) {
		$title       = $category->name;
		$description = ! empty( $category->description ) ? wp_strip_all_tags( $category->description ) : sprintf( 'Browse products in %s', $category->name );
		$url         = self::get_category_url( $category );

		// Get image URL from attachment ID.
		$image = '';
		if ( ! empty( $category->image_id ) ) {
			$image = wp_get_attachment_url( $category->image_id );
		}

		echo "\n<!-- GGM Commerce OpenGraph Tags -->\n";
		echo '<meta property="og:type" content="website" />' . "\n";
		echo '<meta property="og:title" content="' . esc_attr( $title ) . '" />' . "\n";
		echo '<meta property="og:description" content="' . esc_attr( $description ) . '" />' . "\n";
		echo '<meta name="description" content="' . esc_attr( $description ) . '" />' . "\n";
		echo '<meta property="og:url" content="' . esc_url( $url ) . '" />' . "\n";

		if ( $image ) {
			echo '<meta property="og:image" content="' . esc_url( $image ) . '" />' . "\n";
		}

		echo '<meta property="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '" />' . "\n";
		echo "<!-- /GGM Commerce OpenGraph Tags -->\n\n";
	}

	/**
	 * Output OpenGraph tags for a tag archive.
	 *
	 * @param object $tag Tag object.
	 */
	private static function output_tag_tags( $tag ) {
		$title       = $tag->name;
		$description = ! empty( $tag->description ) ? wp_strip_all_tags( $tag->description ) : sprintf( 'Products tagged with %s', $tag->name );
		$url         = self::get_tag_url( $tag );

		echo "\n<!-- GGM Commerce OpenGraph Tags -->\n";
		echo '<meta property="og:type" content="website" />' . "\n";
		echo '<meta property="og:title" content="' . esc_attr( $title ) . '" />' . "\n";
		echo '<meta property="og:description" content="' . esc_attr( $description ) . '" />' . "\n";
		echo '<meta name="description" content="' . esc_attr( $description ) . '" />' . "\n";
		echo '<meta property="og:url" content="' . esc_url( $url ) . '" />' . "\n";
		echo '<meta property="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '" />' . "\n";
		echo "<!-- /GGM Commerce OpenGraph Tags -->\n\n";
	}

	/**
	 * Output OpenGraph tags for the shop page.
	 */
	private static function output_shop_tags() {
		$shop_page_id = get_option( 'ggm_commerce_shop_page_id' );
		$title        = get_the_title( $shop_page_id );
		$description  = get_bloginfo( 'description' ) ?: sprintf( 'Shop at %s', get_bloginfo( 'name' ) );
		$url          = get_permalink( $shop_page_id );

		echo "\n<!-- GGM Commerce OpenGraph Tags -->\n";
		echo '<meta property="og:type" content="website" />' . "\n";
		echo '<meta property="og:title" content="' . esc_attr( $title ) . '" />' . "\n";
		echo '<meta property="og:description" content="' . esc_attr( $description ) . '" />' . "\n";
		echo '<meta name="description" content="' . esc_attr( $description ) . '" />' . "\n";
		echo '<meta property="og:url" content="' . esc_url( $url ) . '" />' . "\n";
		echo '<meta property="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '" />' . "\n";
		echo "<!-- /GGM Commerce OpenGraph Tags -->\n\n";
	}

	/**
	 * Get the URL for a product.
	 *
	 * @param object $product Product object.
	 * @return string Product URL.
	 */
	private static function get_product_url( $product ) {
		$product_details_page_id = get_option( 'ggm_commerce_product_details_page_id' );
		$url_format              = get_option( 'ggm_commerce_url_format', 'slug' );

		if ( 'slug' === $url_format && ! empty( $product->slug ) ) {
			return trailingslashit( get_permalink( $product_details_page_id ) ) . $product->slug . '/';
		}

		return add_query_arg( 'id', $product->id, get_permalink( $product_details_page_id ) );
	}

	/**
	 * Get the URL for a category.
	 *
	 * @param object $category Category object.
	 * @return string Category URL.
	 */
	private static function get_category_url( $category ) {
		$category_page_id = get_option( 'ggm_commerce_category_archive_page_id' );
		return trailingslashit( get_permalink( $category_page_id ) ) . $category->slug . '/';
	}

	/**
	 * Get the URL for a tag.
	 *
	 * @param object $tag Tag object.
	 * @return string Tag URL.
	 */
	private static function get_tag_url( $tag ) {
		$tag_page_id = get_option( 'ggm_commerce_tag_archive_page_id' );
		return trailingslashit( get_permalink( $tag_page_id ) ) . $tag->slug . '/';
	}

	/**
	 * Get the currency code.
	 *
	 * @return string Currency code.
	 */
	private static function get_currency_code() {
		$currency_options = get_option( 'ggm_commerce_currency_options', array() );
		return isset( $currency_options['code'] ) ? $currency_options['code'] : 'GBP';
	}
}
