<?php
/**
 * SEO Plugin Detector
 *
 * Detects active SEO plugins and provides their meta key configurations.
 *
 * @package AIPT\Api\BulkGenerator\SeoMeta\Core
 */

namespace AIPT\Api\BulkGenerator\SeoMeta\Core;

use AIPT\Api\BulkGenerator\SeoMeta\Core\SeoAnalysisService;

/**
 * Static utility class for detecting SEO plugins and retrieving meta key configurations.
 *
 * Supports detection of 6 major SEO plugins with priority ordering:
 * 1. Yoast SEO
 * 2. Rank Math
 * 3. All in One SEO
 * 4. SEOPress
 * 5. The SEO Framework
 * 6. Squirrly
 *
 * @since 2.4.0
 */
class SeoPluginDetector {

	/**
	 * Meta key configurations for each supported SEO plugin.
	 *
	 * @var array
	 */
	private static $meta_keys_config = array(
		'yoast'    => array(
			'title_key'         => '_yoast_wpseo_title',
			'description_key'   => '_yoast_wpseo_metadesc',
			'focus_keyword_key' => '_yoast_wpseo_focuskw',
			'score_key'         => '_yoast_wpseo_content_score',
			'score_type'        => 'yoast',
		),
		'rankmath' => array(
			'title_key'         => 'rank_math_title',
			'description_key'   => 'rank_math_description',
			'focus_keyword_key' => 'rank_math_focus_keyword',
			'score_key'         => 'rank_math_seo_score',
			'score_type'        => 'numeric',
		),
		'aioseo'   => array(
			'title_key'         => '_aioseo_title',
			'description_key'   => '_aioseo_description',
			'focus_keyword_key' => '_aioseo_keywords',
			'score_key'         => '_aioseo_onpage_score',
			'score_type'        => 'numeric',
		),
		'seopress' => array(
			'title_key'         => '_seopress_titles_title',
			'description_key'   => '_seopress_titles_desc',
			'focus_keyword_key' => '_seopress_analysis_target_kw',
			'score_key'         => '_seopress_analysis_target_keyword_score',
			'score_type'        => 'numeric',
		),
		'tsf'      => array(
			'title_key'         => '_genesis_title',
			'description_key'   => '_genesis_description',
			'focus_keyword_key' => null,
			'score_key'         => null,
			'score_type'        => null,
		),
		'squirrly' => array(
			'title_key'         => '_sq_title',
			'description_key'   => '_sq_description',
			'focus_keyword_key' => '_sq_keywords',
			'score_key'         => '_sq_seo_score',
			'score_type'        => 'numeric',
		),
	);

	/**
	 * Detects which SEO plugin is active and returns its configuration.
	 *
	 * Detection follows priority order:
	 * 1. Yoast SEO (WPSEO_VERSION)
	 * 2. Rank Math (RankMath class)
	 * 3. All in One SEO (aioseo function)
	 * 4. SEOPress (seopress_init function)
	 * 5. The SEO Framework (THE_SEO_FRAMEWORK_VERSION)
	 * 6. Squirrly (SQ_VERSION)
	 *
	 * @return array|null Array with keys 'plugin_slug', 'plugin_name', 'meta_keys', or null if no plugin detected.
	 *
	 * @example
	 * $result = SeoPluginDetector::detect();
	 * if ($result) {
	 *     echo $result['plugin_name']; 
	 *     echo $result['meta_keys']['title_key']; 
	 * }
	 */
	public static function detect() {
		$plugin_slug = self::detect_plugin();

		if ( null === $plugin_slug ) {
			return null;
		}

		return array(
			'plugin_slug' => $plugin_slug,
			'plugin_name' => self::get_plugin_name( $plugin_slug ),
			'meta_keys'   => self::$meta_keys_config[ $plugin_slug ],
		);
	}

	/**
	 * Retrieves meta key configuration for a specific SEO plugin.
	 *
	 * @param string $plugin_slug The plugin slug (e.g., 'yoast', 'rankmath').
	 *
	 * @return array|null Array of meta keys or null if plugin slug not found.
	 *
	 * @example
	 * $keys = SeoPluginDetector::get_meta_keys('yoast');
	 * 
	 */
	public static function get_meta_keys( $plugin_slug ) {
		if ( ! isset( self::$meta_keys_config[ $plugin_slug ] ) ) {
			return null;
		}

		return self::$meta_keys_config[ $plugin_slug ];
	}

	/**
	 * Detects which SEO plugin is active by checking for plugin constants and functions.
	 *
	 * @return string|null Plugin slug or null if no plugin detected.
	 */
	private static function detect_plugin() {

		if ( defined( 'WPSEO_VERSION' ) ) {
			return 'yoast';
		}

		if ( class_exists( 'RankMath\\Installer' ) || class_exists( 'RankMath\\Helper' ) || class_exists( 'RankMath' ) ) {
			return 'rankmath';
		}

		if ( function_exists( 'aioseo' ) ) {
			return 'aioseo';
		}

		if ( function_exists( 'seopress_init' ) ) {
			return 'seopress';
		}

		if ( defined( 'THE_SEO_FRAMEWORK_VERSION' ) ) {
			return 'tsf';
		}

		if ( defined( 'SQ_VERSION' ) ) {
			return 'squirrly';
		}

		return null;
	}

	/**
	 * Gets SEO score and related info for a product.
	 *
	 * @param int        $product_id   The product ID.
	 * @param array|null $plugin_config Optional pre-detected plugin config.
	 *
	 * @return array SEO info with score, focus_keyword, has_title, has_description.
	 */
	public static function get_seo_info( $product_id, $plugin_config = null ) {
		if ( null === $plugin_config ) {
			$plugin_config = self::detect();
		}

		$info = array(
			'score'            => null,
			'score_label'      => null,
			'score_source'     => null,
			'focus_keyword'    => null,
			'focus_keywords'   => array(),
			'has_title'        => false,
			'has_description'  => false,
			'meta_title'       => null,
			'meta_description' => null,
			'plugin_name'      => null,
			'analysis_details' => null,
		);

		if ( null === $plugin_config ) {
			$plugin_config = self::get_standalone_config();
		}

		$meta_keys           = $plugin_config['meta_keys'];
		$info['plugin_name'] = $plugin_config['plugin_name'];

		$title_key       = $meta_keys['title_key'] ?? null;
		$description_key = $meta_keys['description_key'] ?? null;

		$title       = $title_key ? \get_post_meta( $product_id, $title_key, true ) : '';
		$description = $description_key ? \get_post_meta( $product_id, $description_key, true ) : '';

		$info['has_title']        = ! empty( $title );
		$info['has_description']  = ! empty( $description );
		$info['meta_title']       = ! empty( $title ) ? $title : null;
		$info['meta_description'] = ! empty( $description ) ? $description : null;

		if ( ! empty( $meta_keys['focus_keyword_key'] ) ) {
			$raw_keywords          = \get_post_meta( $product_id, $meta_keys['focus_keyword_key'], true );
			$info['focus_keyword'] = $raw_keywords;

			if ( ! empty( $raw_keywords ) ) {
				$keywords_array = array_map( 'trim', explode( ',', $raw_keywords ) );
				$keywords_array = array_filter( $keywords_array, function ( $k ) {
					return ! empty( $k );
				} );
				$info['focus_keywords'] = array_values( $keywords_array );
			}
		}

		if ( ! empty( $meta_keys['score_key'] ) ) {
			$raw_score = \get_post_meta( $product_id, $meta_keys['score_key'], true );

			if ( '' !== $raw_score && null !== $raw_score && false !== $raw_score ) {
				$info['score']        = self::normalize_score( $raw_score, $meta_keys['score_type'] );
				$info['score_label']  = SeoAnalysisService::get_score_label( $info['score'] );
				$info['score_source'] = 'plugin';
			}
		}

		$info['analysis_details'] = SeoAnalysisService::analyze(
			$product_id,
			$info['focus_keywords'],
			$plugin_config
		);

		if ( null === $info['score'] && ! empty( $info['focus_keywords'] ) ) {
			$calculated_score = SeoAnalysisService::calculate_score( $info['analysis_details'] );

			if ( null !== $calculated_score ) {
				$info['score']        = $calculated_score;
				$info['score_label']  = SeoAnalysisService::get_score_label( $calculated_score );
				$info['score_source'] = 'calculated';
			}
		}

		return $info;
	}

	/**
	 * Normalizes score to 0-100 range based on plugin type.
	 *
	 * @param mixed  $raw_score  The raw score value.
	 * @param string $score_type The score type ('numeric', 'yoast').
	 *
	 * @return int|null Normalized score (0-100) or null.
	 */
	private static function normalize_score( $raw_score, $score_type ) {

		if ( '' === $raw_score || null === $raw_score || false === $raw_score ) {
			return null;
		}

		if ( 'yoast' === $score_type ) {

			if ( is_string( $raw_score ) ) {
				$string_map = array(
					'good'   => 90,
					'green'  => 90,
					'ok'     => 60,
					'orange' => 60,
					'bad'    => 30,
					'red'    => 30,
				);
				$normalized_string = strtolower( trim( $raw_score ) );
				if ( isset( $string_map[ $normalized_string ] ) ) {
					$raw_score = $string_map[ $normalized_string ];
				} elseif ( ! is_numeric( $raw_score ) ) {
					return null;
				}
			}

			$score_map = array(
				0  => 0,
				30 => 40,
				60 => 70,
				90 => 100,
			);
			$raw = (int) $raw_score;

			if ( isset( $score_map[ $raw ] ) ) {
				return $score_map[ $raw ];
			}

			$map_keys = array_keys( $score_map );
			sort( $map_keys );

			$lower_key = null;
			$upper_key = null;

			foreach ( $map_keys as $key ) {
				if ( $key <= $raw ) {
					$lower_key = $key;
				}
				if ( $key >= $raw && null === $upper_key ) {
					$upper_key = $key;
				}
			}

			if ( null === $lower_key ) {
				return $score_map[ $map_keys[0] ];
			}

			if ( null === $upper_key ) {
				return $score_map[ $map_keys[ count( $map_keys ) - 1 ] ];
			}

			if ( $lower_key === $upper_key ) {
				return $score_map[ $lower_key ];
			}

			$lower_output = $score_map[ $lower_key ];
			$upper_output = $score_map[ $upper_key ];
			$interpolated = $lower_output + ( $upper_output - $lower_output ) * ( $raw - $lower_key ) / ( $upper_key - $lower_key );

			return max( 0, min( 100, (int) round( $interpolated ) ) );
		}

		return max( 0, min( 100, (int) $raw_score ) );
	}

	/**
	 * Gets standalone config for when no SEO plugin is detected.
	 *
	 * @return array Standalone configuration with null meta keys.
	 */
	private static function get_standalone_config() {
		return array(
			'plugin_slug' => 'standalone',
			'plugin_name' => null,
			'meta_keys'   => array(
				'title_key'         => null,
				'description_key'   => null,
				'focus_keyword_key' => null,
				'score_key'         => null,
				'score_type'        => null,
			),
		);
	}

	/**
	 * Gets the human-readable name for a plugin slug.
	 *
	 * @param string $plugin_slug The plugin slug.
	 *
	 * @return string The plugin name.
	 */
	private static function get_plugin_name( $plugin_slug ) {
		$plugin_names = array(
			'yoast'    => 'Yoast SEO',
			'rankmath' => 'Rank Math',
			'aioseo'   => 'All in One SEO',
			'seopress' => 'SEOPress',
			'tsf'      => 'The SEO Framework',
			'squirrly' => 'Squirrly',
		);

		return isset( $plugin_names[ $plugin_slug ] ) ? $plugin_names[ $plugin_slug ] : 'Unknown';
	}
}
