<?php
/** @noinspection PhpIllegalPsrClassPathInspection */

namespace WPDRMS\Utils;

if ( !defined('ABSPATH') ) {
	die('-1');
}

/**
 * Utility class for environment checks and other helper methods.
 */
class Server {
	/**
	 * Returns the official WordPress environment type.
	 *
	 * Thin, testable wrapper over wp_get_environment_type() that normalises the result to one of
	 * the four canonical values and defaults to 'production' (matching WordPress' own default).
	 * Used by license activation to let the server classify a production vs development slot.
	 *
	 * @param string|null $wp_environment_type Optional. wp_get_environment_type() value. Default null.
	 *
	 * @return string One of 'local', 'development', 'staging' or 'production'.
	 */
	public static function getEnvironmentType( ?string $wp_environment_type = null ): string {
		if ( $wp_environment_type === null && function_exists('wp_get_environment_type') ) {
			$wp_environment_type = wp_get_environment_type();
		}
		return in_array( $wp_environment_type, array( 'local', 'development', 'staging', 'production' ), true )
			? $wp_environment_type
			: 'production';
	}

	/**
	 * Determines if the current environment is a local development environment.
	 *
	 * This method checks multiple indicators to ascertain if the environment
	 * is local. It checks:
	 * 1. The official wp_get_environment_type() (local/development/staging).
	 * 2. If WP_DEBUG is defined and true.
	 * 3. If the site URL contains common local development domains.
	 * 4. If the server name is localhost or a loopback address.
	 * 5. If an environment variable (e.g., WP_ENV) is set to 'development'.
	 *
	 * @param bool|null                  $wp_debug             Optional. WP_DEBUG value. Default null.
	 * @param string|null                $site_url             Optional. Site URL. Default null.
	 * @param array<string, string>|null $server               Optional. Server variables. Default null.
	 * @param string|null                $wp_env               Optional. WP_ENV value. Default null.
	 * @param string|null                $wp_environment_type  Optional. wp_get_environment_type() value. Default null.
	 *
	 * @return bool True if it's a local development environment, false otherwise.
	 * @noinspection HttpUrlsUsage
	 */
	public static function isLocalEnvironment(
		?bool $wp_debug = null,
		?string $site_url = null,
		?array $server = null,
		?string $wp_env = null,
		?string $wp_environment_type = null
	): bool {
		// 1. Official WordPress signal: the site can explicitly declare its environment
		// via the WP_ENVIRONMENT_TYPE constant/variable (defaults to 'production').
		if ( $wp_environment_type === null && function_exists('wp_get_environment_type') ) {
			$wp_environment_type = wp_get_environment_type();
		}
		if ( in_array( $wp_environment_type, array( 'local', 'development', 'staging' ), true ) ) {
			return true;
		}

		// 2. Check WP_DEBUG
		if ( $wp_debug === null ) {
			$wp_debug = defined('WP_DEBUG') && WP_DEBUG;
		}
		if ( $wp_debug ) {
			return true;
		}

		// 2. Check site_url
		if ( $site_url === null && function_exists('site_url') ) {
			$site_url = site_url();
		}
		if ( $site_url !== null ) {
			$local_domains = array(
				'dev',
				'develop',
				'development',
				'test',
				'testing',
				'qa',
				'staging',
				'stage',
				'sandbox',
				'preprod',
				'uat',
				'beta',
				'ci',
				'cd',
				'integration',
				'preview',
				'next',
				'feature',
				'canary',
				'rc',
				'experimental',
				'edge',
				'perf',
				'loadtest',
				'regression',
				'support',
				'internal',
				'fix',
				'patch',
				'mock',
				'acceptance',
				'release',
				'interim',
				'alpha',
				'emulation',
				'new',
				'v1',
				'v2',
				'maintenance',
				'bugfix',
				'prelaunch',
				'quality',
				'verification',
				'pilot',
			);
			/**
			 * Matches only if they start with https://{domain}...
			 */
			foreach ( $local_domains as $domain ) {
				$variations = array(
					$domain . '.',
					$domain . '-',
					$domain . '_',
					$domain . '0',
					$domain . '1',
					$domain . '2',
					$domain . '3',
					$domain . '4',
					$domain . '5',
					$domain . '6',
					$domain . '7',
					$domain . '8',
					$domain . '9',
				);
				foreach ( $variations as $variation ) {
					if ( strpos($site_url, '://' . $variation) !== false ) {
						return true;
					}
				}
			}

			/**
			 * Matches if contains it anywhere
			 */
			$known_test_domains = array(
				'http://',
				'localhost',
				'127.0.0.1',
				'::1',
				'wpengine.com',
				'.wpenginepowered.com',
				'.kinsta.cloud',
				'.local/',
				'.test/',
				'.lan/',
			);
			foreach ( $known_test_domains as $domain ) {
				if ( strpos($site_url, $domain) !== false ) {
					return true;
				}
			}

			/**
			 * Matches if ends with
			 */
			$domain_endings = array(
				'.test',
				'.local',
				'.lan',
			);
			foreach ( $domain_endings as $domain ) {
				if ( str_ends_with($site_url, $domain) ) {
					return true;
				}
			}
		}

		// 3. Check server name
		if ( $server === null ) {
			$server = $_SERVER;
		}
		$server_name        = isset($server['SERVER_NAME']) ? strtolower($server['SERVER_NAME']) : '';
		$local_server_names = array( 'localhost', '127.0.0.1', '::1' );

		if ( in_array($server_name, $local_server_names, true) ) {
			return true;
		}

		// 4. Check WP_ENV
		if ( $wp_env === null ) {
			$wp_env = getenv('WP_ENV');
		}
		if ( $wp_env && strtolower($wp_env) === 'development' ) {
			return true;
		}

		// Not a local environment
		return false;
	}

	public static function getHTTPHost(): string {
		if ( isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST'] !== '' ) {
			return $_SERVER['HTTP_HOST']; // phpcs:ignore
		}

		$bloginfo = get_bloginfo('url');
		$host     = wp_parse_url($bloginfo, PHP_URL_HOST);

		if ( is_string($host) && trim($host) !== '' ) {
			return trim($host);
		}

		return 'unknown.host';
	}

	public static function getCleanUrlPath( string $url ): ?string {
		$path = wp_parse_url( $url, PHP_URL_PATH );
		if ( ! $path ) {
			return null;
		}

		// Normalize path
		$path = ltrim( $path, '/' );
		$path = untrailingslashit( $path );

		return $path === '/' || $path === '' ? null : $path;
	}

	public static function getCleanReferrerPath(): ?string {
		$referer = wp_get_referer();
		if ( ! $referer ) {
			return null;
		}

		return self::getCleanUrlPath($referer);
	}

	public static function requestUriContains( string $needle ): bool {
		// phpcs:disable
		return strpos($_SERVER['REQUEST_URI'], $needle) !== false;
	}

	public static function refererContains( string $needle ): bool {
		$referer = wp_get_referer();
		if ( ! $referer ) {
			return false;
		}

		return strpos($referer, $needle) !== false;
	}
}
