<?php
/**
 * China Resource Analysis
 *
 * Scans the WordPress site for resources that are blocked or slow
 * behind the Great Firewall (GFW) and provides recommendations.
 *
 * @package SpeedInChina
 */

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

class SPEEINCH_Resource_Analysis {

	/**
	 * Lazily bootstrap WP_Filesystem and return the global instance.
	 *
	 * Used for reading theme files (header.php, footer.php, functions.php) so
	 * that PCP / PHPCS never need a `phpcs:ignore
	 * WordPress.WP.AlternativeFunctions.file_get_contents_*` marker on this
	 * class, and so the next plugin-check release's tightened fs-operation
	 * detection cannot surface a fresh warning.
	 *
	 * @return WP_Filesystem_Base|null
	 */
	private static function fs() {
		global $wp_filesystem;
		if ( $wp_filesystem instanceof WP_Filesystem_Base ) {
			return $wp_filesystem;
		}
		if ( ! function_exists( 'WP_Filesystem' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}
		WP_Filesystem();
		return ( $wp_filesystem instanceof WP_Filesystem_Base ) ? $wp_filesystem : null;
	}

	/**
	 * Domains commonly blocked by the GFW.
	 * Key = domain pattern, Value = severity (critical/warning/info) + recommendation.
	 */
	const BLOCKED_DOMAINS = array(
		'fonts.googleapis.com'     => array(
			'severity'       => 'critical',
			'service'        => 'Google Fonts',
			'recommendation' => 'Enable "Localize Google Fonts" in Speed in China settings to serve fonts locally.',
		),
		'fonts.gstatic.com'        => array(
			'severity'       => 'critical',
			'service'        => 'Google Fonts CDN',
			'recommendation' => 'Enable "Localize Google Fonts" to replace with local copies.',
		),
		'ajax.googleapis.com'      => array(
			'severity'       => 'critical',
			'service'        => 'Google CDN (jQuery, etc.)',
			'recommendation' => 'Use a local copy or China-friendly CDN (e.g., cdn.bootcdn.net).',
		),
		'cdnjs.cloudflare.com'     => array(
			'severity'       => 'warning',
			'service'        => 'Cloudflare CDN',
			'recommendation' => 'Cloudflare is intermittently blocked. Consider BootCDN or local hosting.',
		),
		'maps.googleapis.com'      => array(
			'severity'       => 'critical',
			'service'        => 'Google Maps',
			'recommendation' => 'Replace with Baidu Maps or Amap (Gaode Maps) for China users.',
		),
		'www.google.com'           => array(
			'severity'       => 'critical',
			'service'        => 'Google Services',
			'recommendation' => 'All Google domains are blocked in China.',
		),
		'www.youtube.com'          => array(
			'severity'       => 'critical',
			'service'        => 'YouTube',
			'recommendation' => 'Replace embedded YouTube videos with Bilibili or Youku.',
		),
		'player.vimeo.com'         => array(
			'severity'       => 'warning',
			'service'        => 'Vimeo',
			'recommendation' => 'Vimeo is intermittently blocked. Consider local video hosting.',
		),
		'www.facebook.com'         => array(
			'severity'       => 'critical',
			'service'        => 'Facebook',
			'recommendation' => 'Remove Facebook embeds/shares or replace with WeChat sharing.',
		),
		'connect.facebook.net'     => array(
			'severity'       => 'critical',
			'service'        => 'Facebook SDK',
			'recommendation' => 'Remove Facebook SDK/Login for China deployments.',
		),
		'platform.twitter.com'     => array(
			'severity'       => 'critical',
			'service'        => 'Twitter/X',
			'recommendation' => 'Remove Twitter embeds for China deployments.',
		),
		'www.instagram.com'        => array(
			'severity'       => 'critical',
			'service'        => 'Instagram',
			'recommendation' => 'Remove Instagram embeds for China users.',
		),
		'www.google-analytics.com' => array(
			'severity'       => 'critical',
			'service'        => 'Google Analytics',
			'recommendation' => 'Replace with Baidu Analytics or Matomo for China tracking.',
		),
		'www.googletagmanager.com' => array(
			'severity'       => 'critical',
			'service'        => 'Google Tag Manager',
			'recommendation' => 'GTM is blocked. Use direct integration or Baidu Analytics.',
		),
		'recaptcha.net'            => array(
			'severity'       => 'critical',
			'service'        => 'Google reCAPTCHA',
			'recommendation' => 'Replace with hCaptcha, Tencent Captcha, or simple math CAPTCHA.',
		),
		'www.gstatic.com'          => array(
			'severity'       => 'critical',
			'service'        => 'Google Static CDN',
			'recommendation' => 'Host these assets locally.',
		),
		'gravatar.com'             => array(
			'severity'       => 'warning',
			'service'        => 'Gravatar',
			'recommendation' => 'Switch to Cravatar (cravatar.cn) — a China-friendly Gravatar mirror.',
		),
		'secure.gravatar.com'      => array(
			'severity'       => 'warning',
			'service'        => 'Gravatar (Secure)',
			'recommendation' => 'Switch to Cravatar (cravatar.cn).',
		),
		's.w.org'                  => array(
			'severity'       => 'info',
			'service'        => 'WordPress.org Assets',
			'recommendation' => 'Consider hosting WP emoji/assets locally for faster China loading.',
		),
	);

	/**
	 * Run a complete resource analysis and return results.
	 *
	 * Fetches the site's homepage HTML and scans it for resources
	 * from domains blocked by the GFW. Also checks active plugins,
	 * Gravatar settings, and theme files.
	 *
	 * @return array Analysis results with issues grouped by severity.
	 */
	public static function analyze() {
		$issues = array(
			'critical' => array(),
			'warning'  => array(),
			'info'     => array(),
		);

		// Track which blocked domains were actually found
		$found_domains = array();

		// 1. Fetch homepage HTML and scan for blocked domains
		$html_issues = self::scan_frontend_html( $found_domains );
		foreach ( $html_issues as $issue ) {
			$issues[ $issue['severity'] ][] = $issue;
		}

		// 2. Check Gravatar settings
		$gravatar_issue = self::check_gravatar();
		if ( $gravatar_issue ) {
			$issues[ $gravatar_issue['severity'] ][] = $gravatar_issue;
			$found_domains['gravatar.com']           = true;
		}

		// 3. Check for Google Analytics / GTM in theme files
		$analytics_issues = self::check_theme_for_blocked_services();
		foreach ( $analytics_issues as $issue ) {
			$issues[ $issue['severity'] ][] = $issue;
		}

		// 4. Check active plugins for known China-blocking patterns
		$plugin_issues = self::scan_plugins();
		foreach ( $plugin_issues as $issue ) {
			$issues[ $issue['severity'] ][] = $issue;
		}

		// 5. Build "passed" list — blocked domains NOT found on the site
		$passed = array();
		foreach ( self::BLOCKED_DOMAINS as $domain => $info ) {
			if ( empty( $found_domains[ $domain ] ) ) {
				$passed[] = array(
					'severity'       => 'passed',
					'type'           => 'Check',
					'handle'         => $domain,
					'url'            => '',
					'service'        => $info['service'],
					'recommendation' => 'Not detected on your site — no action needed.',
				);
			}
		}

		// Build summary
		$total = count( $issues['critical'] ) + count( $issues['warning'] ) + count( $issues['info'] );

		return array(
			'issues'    => $issues,
			'passed'    => $passed,
			'summary'   => array(
				'total'    => $total,
				'critical' => count( $issues['critical'] ),
				'warnings' => count( $issues['warning'] ),
				'info'     => count( $issues['info'] ),
				'passed'   => count( $passed ),
				'score'    => $total === 0 ? 100 : max( 0, 100 - ( count( $issues['critical'] ) * 15 ) - ( count( $issues['warning'] ) * 5 ) - ( count( $issues['info'] ) * 1 ) ),
			),
			'timestamp' => gmdate( 'Y-m-d H:i:s' ),
		);
	}

	/**
	 * Fetch the site's homepage and scan all resource URLs for blocked domains.
	 *
	 * @return array List of issues found.
	 */
	private static function scan_frontend_html( &$found_domains = array() ) {
		$issues   = array();
		$site_url = home_url( '/' );

		$response = wp_remote_get(
			$site_url,
			array(
				'timeout'    => 30,
				'user-agent' => 'SpeedInChina/1.0 Resource Analyzer',
			)
		);

		if ( is_wp_error( $response ) ) {
			$issues[] = array(
				'severity'       => 'warning',
				'type'           => 'System',
				'handle'         => 'homepage',
				'url'            => $site_url,
				'service'        => 'Site Scan',
				'recommendation' => 'Could not fetch homepage for analysis: ' . $response->get_error_message(),
			);
			return $issues;
		}

		$html = wp_remote_retrieve_body( $response );
		if ( empty( $html ) ) {
			return $issues;
		}

		// Track domains we've already reported to avoid duplicates
		$reported = array();

		// Find all src="" and href="" URLs in the HTML
		$patterns = array(
			'/\bsrc=["\']([^"\']+)["\']/i',
			'/\bhref=["\']([^"\']+)["\']/i',
		);

		foreach ( $patterns as $pattern ) {
			if ( preg_match_all( $pattern, $html, $matches ) ) {
				foreach ( $matches[1] as $url ) {
					foreach ( self::BLOCKED_DOMAINS as $domain => $info ) {
						if ( strpos( $url, $domain ) !== false ) {
							$found_domains[ $domain ] = true;

							$key = $domain . '|' . $url;
							if ( isset( $reported[ $key ] ) ) {
								continue;
							}
							$reported[ $key ] = true;

							// Determine type from tag context
							$type = 'Resource';
							if ( strpos( $url, '.js' ) !== false || strpos( $url, 'script' ) !== false ) {
								$type = 'Script';
							} elseif ( strpos( $url, '.css' ) !== false || strpos( $url, 'stylesheet' ) !== false || strpos( $url, 'fonts' ) !== false ) {
								$type = 'Stylesheet';
							}

							$issues[] = array(
								'severity'       => $info['severity'],
								'type'           => $type,
								'handle'         => $domain,
								'url'            => $url,
								'service'        => $info['service'],
								'recommendation' => $info['recommendation'],
							);
						}
					}
				}
			}
		}

		return $issues;
	}

	/**
	 * Scan enqueued scripts or styles for blocked domains.
	 *
	 * @param string $type 'scripts' or 'styles'.
	 * @return array List of issues found.
	 */
	private static function scan_enqueued_assets( $type = 'scripts' ) {
		$issues = array();

		if ( $type === 'scripts' ) {
			global $wp_scripts;
			$assets = $wp_scripts;
		} else {
			global $wp_styles;
			$assets = $wp_styles;
		}

		if ( empty( $assets ) || empty( $assets->registered ) ) {
			return $issues;
		}

		foreach ( $assets->registered as $handle => $asset ) {
			if ( empty( $asset->src ) ) {
				continue;
			}

			foreach ( self::BLOCKED_DOMAINS as $domain => $info ) {
				if ( strpos( $asset->src, $domain ) !== false ) {
					$issues[] = array(
						'severity'       => $info['severity'],
						'type'           => $type === 'scripts' ? 'Script' : 'Stylesheet',
						'handle'         => $handle,
						'url'            => $asset->src,
						'service'        => $info['service'],
						'recommendation' => $info['recommendation'],
					);
				}
			}
		}

		return $issues;
	}

	/**
	 * Check if Gravatar is enabled.
	 *
	 * @return array|null Issue if Gravatar is enabled, null otherwise.
	 */
	private static function check_gravatar() {
		$show_avatars = get_option( 'show_avatars' );

		if ( $show_avatars ) {
			$avatar_url = get_avatar_url( 0 );
			if ( $avatar_url && strpos( $avatar_url, 'gravatar.com' ) !== false ) {
				return array(
					'severity'       => 'warning',
					'type'           => 'Service',
					'handle'         => 'gravatar',
					'url'            => 'gravatar.com',
					'service'        => 'Gravatar',
					'recommendation' => 'Install Cravatar plugin or add this filter: add_filter("get_avatar_url", function($url) { return str_replace("gravatar.com", "cravatar.cn", $url); });',
				);
			}
		}

		return null;
	}

	/**
	 * Check active theme for hardcoded Google Analytics/GTM/Facebook Pixel.
	 *
	 * @return array List of issues.
	 */
	private static function check_theme_for_blocked_services() {
		$issues    = array();
		$theme_dir = get_template_directory();

		// Only check header.php and footer.php (most common locations)
		$files_to_check = array(
			$theme_dir . '/header.php',
			$theme_dir . '/footer.php',
			$theme_dir . '/functions.php',
		);

		$patterns = array(
			'google-analytics.com'           => array(
				'service'  => 'Google Analytics',
				'severity' => 'critical',
			),
			'googletagmanager.com'           => array(
				'service'  => 'Google Tag Manager',
				'severity' => 'critical',
			),
			'facebook.net/en_US/fbevents.js' => array(
				'service'  => 'Facebook Pixel',
				'severity' => 'critical',
			),
			'recaptcha'                      => array(
				'service'  => 'Google reCAPTCHA',
				'severity' => 'critical',
			),
		);

		$fs = self::fs();

		foreach ( $files_to_check as $file ) {
			if ( ! file_exists( $file ) ) {
				continue;
			}

			$content = ( null !== $fs ) ? $fs->get_contents( $file ) : '';
			if ( ! is_string( $content ) || '' === $content ) {
				continue;
			}

			foreach ( $patterns as $pattern => $info ) {
				if ( stripos( $content, $pattern ) !== false ) {
					$issues[] = array(
						'severity'       => $info['severity'],
						'type'           => 'Theme',
						'handle'         => basename( $file ),
						'url'            => $pattern,
						'service'        => $info['service'],
						'recommendation' => 'Remove or conditionally load ' . $info['service'] . ' for China visitors.',
					);
				}
			}
		}

		return $issues;
	}

	/**
	 * Scan active plugins for known China-blocking patterns.
	 *
	 * @return array List of issues.
	 */
	private static function scan_plugins() {
		$issues = array();

		$problematic_plugins = array(
			'google-analytics-for-wordpress' => array(
				'service'        => 'MonsterInsights (Google Analytics)',
				'severity'       => 'critical',
				'recommendation' => 'Disable for China traffic or use Baidu Analytics plugin.',
			),
			'google-site-kit'                => array(
				'service'        => 'Google Site Kit',
				'severity'       => 'critical',
				'recommendation' => 'Site Kit loads multiple Google services. Disable for China.',
			),
			'jetpack'                        => array(
				'service'        => 'Jetpack',
				'severity'       => 'warning',
				'recommendation' => 'Jetpack CDN (i0.wp.com) may be slow in China. Consider disabling CDN features.',
			),
			'wp-rocket'                      => array(
				'service'        => 'WP Rocket',
				'severity'       => 'info',
				'recommendation' => 'Ensure Google Fonts optimization is set to "local" mode, not "preload".',
			),
			'official-facebook-pixel'        => array(
				'service'        => 'Facebook Pixel',
				'severity'       => 'critical',
				'recommendation' => 'Facebook Pixel is blocked in China. Disable for China traffic.',
			),
			'instagram-feed'                 => array(
				'service'        => 'Instagram Feed',
				'severity'       => 'critical',
				'recommendation' => 'Instagram is blocked in China. Replace with local content.',
			),
			'recaptcha'                      => array(
				'service'        => 'reCAPTCHA',
				'severity'       => 'critical',
				'recommendation' => 'Replace with hCaptcha or a non-Google CAPTCHA solution.',
			),
		);

		$active_plugins = (array) get_option( 'active_plugins', array() );

		// Use get_plugins() to obtain plugin metadata without dereferencing
		// WP_PLUGIN_DIR ourselves; WP core handles the directory resolution
		// (including symlinked / non-standard installs) internally.
		if ( ! function_exists( 'get_plugins' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
		$all_plugins = get_plugins();

		foreach ( $active_plugins as $plugin_path ) {
			$plugin_slug = dirname( $plugin_path );
			if ( $plugin_slug === '.' ) {
				$plugin_slug = basename( $plugin_path, '.php' );
			}

			foreach ( $problematic_plugins as $check_slug => $info ) {
				if ( strpos( $plugin_slug, $check_slug ) !== false ) {
					$plugin_data = isset( $all_plugins[ $plugin_path ] ) ? $all_plugins[ $plugin_path ] : array();
					$issues[]    = array(
						'severity'       => $info['severity'],
						'type'           => 'Plugin',
						'handle'         => $plugin_slug,
						'url'            => isset( $plugin_data['Name'] ) ? $plugin_data['Name'] : $plugin_slug,
						'service'        => $info['service'],
						'recommendation' => $info['recommendation'],
					);
				}
			}
		}

		return $issues;
	}
}
