<?php

declare(strict_types=1);

namespace SecurWP\Modules\Firewall\SearchTrust;

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

use SecurWP\Includes\SitePathResolver;
use SecurWP\Modules\Hardening\Hardening;

final class SearchTrustScopeBuilder {
	/**
	 * @return array{protected_paths: array<int, string>, protected_prefixes: array<int, string>, scope_hash: string}
	 */
	public static function build_from_wordpress(): array {
		$protected_paths = [];
		$protected_prefixes = [];

		foreach (
			[
				site_url( 'wp-login.php' ),
				site_url( 'wp-signup.php' ),
				site_url( 'wp-register.php' ),
				site_url( 'wp-activate.php' ),
				site_url( 'xmlrpc.php' ),
				site_url( 'wp-cron.php' ),
				site_url( 'wp-comments-post.php' ),
				site_url( 'wp-trackback.php' ),
				site_url( 'wp-mail.php' ),
			] as $url
		) {
			self::add_public_path( $protected_paths, (string) $url );
		}

		$admin_base = SitePathResolver::get_public_path_from_url( admin_url( '/' ), false );
		if ( is_string( $admin_base ) && $admin_base !== '' && $admin_base !== '/' ) {
			$protected_prefixes[] = $admin_base;
		}

		$rest_prefix = self::get_rest_public_prefix();
		if ( is_string( $rest_prefix ) && $rest_prefix !== '' ) {
			$protected_prefixes[] = $rest_prefix;
		}

		$hardening_settings = Hardening::get_saved_settings();
		if ( ! empty( $hardening_settings['rename_login_url_enabled'] ) ) {
			$login_slug = sanitize_title( (string) ( $hardening_settings['rename_login_url_slug'] ?? '' ) );
			if ( $login_slug !== '' ) {
				self::add_public_path( $protected_paths, home_url( '/' . $login_slug ) );
			}

			$register_slug = trim( (string) ( $hardening_settings['rename_login_url_register_slug'] ?? '' ) );
			if ( $register_slug !== '' && strtolower( $register_slug ) !== 'wp-signup.php' ) {
				self::add_public_path( $protected_paths, home_url( '/' . sanitize_title( $register_slug ) ) );
			}
		}

		$scope = [
			'protected_paths' => SearchTrustCore::normalize_request_scope_paths( $protected_paths ),
			'protected_prefixes' => SearchTrustCore::normalize_request_scope_prefixes( $protected_prefixes ),
		];

		$scope['scope_hash'] = SearchTrustCore::build_scope_hash( $scope );

		return $scope;
	}

	/**
	 * @param array<int, string> $bucket
	 */
	private static function add_public_path( array &$bucket, string $url ): void {
		$path = SitePathResolver::get_public_path_from_url( $url, false );
		if ( is_string( $path ) && $path !== '' ) {
			$bucket[] = $path;
		}
	}

	private static function get_rest_public_prefix(): ?string {
		$rest_url = self::safe_rest_url();
		if ( is_string( $rest_url ) && $rest_url !== '' ) {
			$rest_query = wp_parse_url( $rest_url, PHP_URL_QUERY );
			$rest_path  = SitePathResolver::get_public_path_from_url( $rest_url, false );

			if (
				( ! is_string( $rest_query ) || strpos( $rest_query, 'rest_route=' ) === false )
				&& is_string( $rest_path )
				&& $rest_path !== ''
				&& $rest_path !== '/'
				&& $rest_path !== '/index.php'
			) {
				return $rest_path;
			}
		}

		if ( ! function_exists( 'rest_get_url_prefix' ) || ! function_exists( 'get_option' ) ) {
			return null;
		}

		$permalink_structure = (string) get_option( 'permalink_structure' );
		if ( $permalink_structure === '' ) {
			return null;
		}

		$rest_prefix = trim( (string) rest_get_url_prefix(), '/' );
		if ( $rest_prefix === '' ) {
			return null;
		}

		$path_segments = [];
		$site_base     = trim( (string) wp_parse_url( home_url( '/' ), PHP_URL_PATH ), '/' );
		if ( $site_base !== '' ) {
			$path_segments[] = $site_base;
		}

		if ( self::using_index_permalinks_fallback( $permalink_structure ) ) {
			$path_segments[] = 'index.php';
		}

		$path_segments[] = $rest_prefix;

		return '/' . implode( '/', $path_segments );
	}

	private static function safe_rest_url(): ?string {
		if ( ! function_exists( 'rest_url' ) ) {
			return null;
		}

		$wp_rewrite = $GLOBALS['wp_rewrite'] ?? null;
		if ( ! did_action( 'init' ) && ! is_object( $wp_rewrite ) ) {
			return null;
		}

		try {
			return (string) rest_url( '/' );
		} catch ( \Throwable $e ) {
			return null;
		}
	}

	private static function using_index_permalinks_fallback( string $permalink_structure ): bool {
		$wp_rewrite = $GLOBALS['wp_rewrite'] ?? null;
		if ( is_object( $wp_rewrite ) && method_exists( $wp_rewrite, 'using_index_permalinks' ) ) {
			try {
				return (bool) $wp_rewrite->using_index_permalinks();
			} catch ( \Throwable $e ) {
				return false;
			}
		}

		return strpos( $permalink_structure, 'index.php' ) !== false;
	}
}
