<?php
/**
 * Registry of recognised AI bot user agents.
 *
 * @package WPLens
 */

namespace WPLens\Crawler;

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

final class BotRegistry {

	/**
	 * Seed list — extendable via filter `wplens/bots`.
	 *
	 * Each entry: slug => [ family, label, ua_contains ]
	 *
	 * @return array<string, array{family:string, label:string, ua:string}>
	 */
	public static function all(): array {
		$bots = array(
			'gptbot'              => array( 'family' => 'OpenAI',      'label' => 'GPTBot',              'ua' => 'GPTBot' ),
			'oai-searchbot'       => array( 'family' => 'OpenAI',      'label' => 'OAI-SearchBot',       'ua' => 'OAI-SearchBot' ),
			'chatgpt-user'        => array( 'family' => 'OpenAI',      'label' => 'ChatGPT-User',        'ua' => 'ChatGPT-User' ),
			'claudebot'           => array( 'family' => 'Anthropic',   'label' => 'ClaudeBot',           'ua' => 'ClaudeBot' ),
			'claude-searchbot'    => array( 'family' => 'Anthropic',   'label' => 'Claude-SearchBot',    'ua' => 'Claude-SearchBot' ),
			'claude-user'         => array( 'family' => 'Anthropic',   'label' => 'Claude-User',         'ua' => 'Claude-User' ),
			'anthropic-ai'        => array( 'family' => 'Anthropic',   'label' => 'anthropic-ai',        'ua' => 'anthropic-ai' ),
			'perplexitybot'       => array( 'family' => 'Perplexity',  'label' => 'PerplexityBot',       'ua' => 'PerplexityBot' ),
			'perplexity-user'     => array( 'family' => 'Perplexity',  'label' => 'Perplexity-User',     'ua' => 'Perplexity-User' ),
			'google-extended'     => array( 'family' => 'Google',      'label' => 'Google-Extended',     'ua' => 'Google-Extended' ),
			'googlebot'           => array( 'family' => 'Google',      'label' => 'Googlebot',           'ua' => 'Googlebot' ),
			'bingbot'             => array( 'family' => 'Microsoft',   'label' => 'Bingbot',             'ua' => 'bingbot' ),
			'meta-externalagent'  => array( 'family' => 'Meta',        'label' => 'Meta-ExternalAgent',  'ua' => 'Meta-ExternalAgent' ),
			'facebookbot'         => array( 'family' => 'Meta',        'label' => 'FacebookBot',         'ua' => 'FacebookBot' ),
			'deepseekbot'         => array( 'family' => 'DeepSeek',    'label' => 'DeepSeekBot',         'ua' => 'DeepSeekBot' ),
			'applebot-extended'   => array( 'family' => 'Apple',       'label' => 'Applebot-Extended',   'ua' => 'Applebot-Extended' ),
			'ccbot'               => array( 'family' => 'CommonCrawl', 'label' => 'CCBot',               'ua' => 'CCBot' ),
			'mistralai-user'      => array( 'family' => 'Mistral',     'label' => 'MistralAI-User',      'ua' => 'MistralAI-User' ),
		);

		/**
		 * Filter the list of recognised AI bots.
		 *
		 * @param array $bots Registry keyed by slug.
		 */
		return apply_filters( 'wplens/bots', $bots );
	}

	/**
	 * Match a user agent to a registered bot. Returns null if no match.
	 *
	 * @return array{slug:string, family:string, label:string, ua:string}|null
	 */
	public static function match( string $user_agent ): ?array {
		if ( '' === $user_agent ) {
			return null;
		}

		$cache_key = 'wplens_bot_regex_v1';
		$regex     = get_transient( $cache_key );

		if ( false === $regex || ! is_string( $regex ) ) {
			$bots     = self::all();
			$patterns = array();
			foreach ( $bots as $slug => $info ) {
				$patterns[ $slug ] = preg_quote( $info['ua'], '#' );
			}
			$regex = '#(' . implode( '|', $patterns ) . ')#i';
			set_transient( $cache_key, $regex, HOUR_IN_SECONDS );
		}

		if ( preg_match( $regex, $user_agent, $matches ) ) {
			$matched = strtolower( $matches[1] );
			foreach ( self::all() as $slug => $info ) {
				if ( stripos( $matched, strtolower( $info['ua'] ) ) !== false ) {
					return array_merge( array( 'slug' => $slug ), $info );
				}
			}
		}

		return null;
	}

	/**
	 * Clear the compiled-regex cache. Call when the filter output may have changed.
	 */
	public static function flush_cache(): void {
		delete_transient( 'wplens_bot_regex_v1' );
	}
}
