<?php
/**
 * Canonical URL analyzer.
 *
 * Checks canonical URL configuration and potential duplicate content issues.
 *
 * @package MonitorCat\Modules\Seo\Analyzer
 */

declare(strict_types=1);

namespace MonitorCat\Modules\Seo\Analyzer;

defined( 'ABSPATH' ) || exit;

/**
 * Analyzes canonical URL setup and duplicate content risks.
 */
final class CanonicalAnalyzer {

	/**
	 * Run the canonical analysis on a post.
	 *
	 * @param int $post_id The post ID to analyze.
	 * @return array{score: int, status: string, checks: array<int, array{label: string, status: string, message: string, value: string|null}>}
	 */
	public function analyze( int $post_id ): array {
		$checks = array();

		$checks[] = $this->check_wp_canonical( $post_id );
		$checks[] = $this->check_seo_plugin_canonical( $post_id );
		$checks[] = $this->check_scheme_consistency();
		$checks[] = $this->check_permalink_structure();

		$score  = $this->calculate_score( $checks );
		$status = $this->determine_status( $score );

		return array(
			'score'  => $score,
			'status' => $status,
			'checks' => $checks,
		);
	}

	/**
	 * Check if WordPress generates a canonical URL for this post.
	 *
	 * @param int $post_id The post ID.
	 * @return array{label: string, status: string, message: string, value: string|null}
	 */
	private function check_wp_canonical( int $post_id ): array {
		$permalink = get_permalink( $post_id );

		if ( ! $permalink ) {
			return array(
				'label'   => __( 'WordPress Canonical', 'monitor-cat' ),
				'status'  => 'fail',
				'message' => __( 'Could not determine the post permalink.', 'monitor-cat' ),
				'value'   => null,
			);
		}

		// WordPress adds rel_canonical via wp_head since 2.9.
		return array(
			'label'   => __( 'WordPress Canonical', 'monitor-cat' ),
			'status'  => 'pass',
			'message' => __( 'WordPress will output a canonical URL via wp_head.', 'monitor-cat' ),
			'value'   => $permalink,
		);
	}

	/**
	 * Check if an SEO plugin provides a canonical override.
	 *
	 * @param int $post_id The post ID.
	 * @return array{label: string, status: string, message: string, value: string|null}
	 */
	private function check_seo_plugin_canonical( int $post_id ): array {
		$canonical_keys = array(
			'_yoast_wpseo_canonical',
			'_aioseo_canonical_url',
			'rank_math_canonical_url',
		);

		foreach ( $canonical_keys as $key ) {
			$value = get_post_meta( $post_id, $key, true );
			if ( ! empty( $value ) && is_string( $value ) ) {
				return array(
					'label'   => __( 'Canonical Override', 'monitor-cat' ),
					'status'  => 'pass',
					'message' => __( 'A custom canonical URL is set via an SEO plugin.', 'monitor-cat' ),
					'value'   => $value,
				);
			}
		}

		return array(
			'label'   => __( 'Canonical Override', 'monitor-cat' ),
			'status'  => 'pass',
			'message' => __( 'No canonical override set. The default WordPress canonical will be used.', 'monitor-cat' ),
			'value'   => null,
		);
	}

	/**
	 * Check for scheme (HTTP/HTTPS) consistency.
	 *
	 * @return array{label: string, status: string, message: string, value: string|null}
	 */
	private function check_scheme_consistency(): array {
		$site_url = site_url();
		$home_url = home_url();

		$site_scheme = wp_parse_url( $site_url, PHP_URL_SCHEME );
		$home_scheme = wp_parse_url( $home_url, PHP_URL_SCHEME );

		if ( 'https' === $site_scheme && 'https' === $home_scheme ) {
			return array(
				'label'   => __( 'HTTPS Consistency', 'monitor-cat' ),
				'status'  => 'pass',
				'message' => __( 'Both site URL and home URL use HTTPS.', 'monitor-cat' ),
				'value'   => 'https',
			);
		}

		if ( $site_scheme !== $home_scheme ) {
			return array(
				'label'   => __( 'HTTPS Consistency', 'monitor-cat' ),
				'status'  => 'fail',
				/* translators: 1: site URL scheme, 2: home URL scheme */
				'message' => sprintf( __( 'Scheme mismatch: site URL uses %1$s, home URL uses %2$s. This can cause duplicate content issues.', 'monitor-cat' ), (string) $site_scheme, (string) $home_scheme ),
				'value'   => sprintf( '%s / %s', (string) $site_scheme, (string) $home_scheme ),
			);
		}

		return array(
			'label'   => __( 'HTTPS Consistency', 'monitor-cat' ),
			'status'  => 'warning',
			'message' => __( 'Site is not using HTTPS. HTTPS is recommended for SEO and security.', 'monitor-cat' ),
			'value'   => (string) $site_scheme,
		);
	}

	/**
	 * Check if pretty permalinks are enabled.
	 *
	 * @return array{label: string, status: string, message: string, value: string|null}
	 */
	private function check_permalink_structure(): array {
		$structure = get_option( 'permalink_structure', '' );

		if ( ! empty( $structure ) ) {
			return array(
				'label'   => __( 'Permalink Structure', 'monitor-cat' ),
				'status'  => 'pass',
				/* translators: %s: permalink structure */
				'message' => sprintf( __( 'Pretty permalinks are enabled: %s', 'monitor-cat' ), $structure ),
				'value'   => $structure,
			);
		}

		return array(
			'label'   => __( 'Permalink Structure', 'monitor-cat' ),
			'status'  => 'fail',
			'message' => __( 'Using plain permalinks (?p=123). Pretty permalinks are strongly recommended for SEO.', 'monitor-cat' ),
			'value'   => '?p=',
		);
	}

	/**
	 * Calculate weighted score from checks.
	 *
	 * @param array<int, array{label: string, status: string, message: string, value: string|null}> $checks The checks array.
	 * @return int Score from 0 to 100.
	 */
	private function calculate_score( array $checks ): int {
		if ( empty( $checks ) ) {
			return 0;
		}

		$weights = array( 30, 20, 25, 25 );
		$total   = 0;

		foreach ( $checks as $index => $check ) {
			$weight     = $weights[ $index ] ?? 25;
			$multiplier = 'pass' === $check['status'] ? 1.0 : ( 'warning' === $check['status'] ? 0.5 : 0.0 );
			$total     += $weight * $multiplier;
		}

		return (int) round( $total );
	}

	/**
	 * Determine overall status from score.
	 *
	 * @param int $score The calculated score.
	 * @return string 'pass', 'warning', or 'fail'.
	 */
	private function determine_status( int $score ): string {
		if ( $score >= 80 ) {
			return 'pass';
		}

		if ( $score >= 50 ) {
			return 'warning';
		}

		return 'fail';
	}
}
