<?php
namespace PageVICO\Geo;

defined( 'ABSPATH' ) || exit;

use PageVICO\Cache\CacheManager;

class GeoService {
	/**
	 * Common country names to ISO codes mapping
	 * 
	 * @var array
	 */
	public static $country_codes = array(
		'United States'        => 'US',
		'United Kingdom'       => 'GB',
		'Canada'               => 'CA',
		'Australia'            => 'AU',
		'Germany'              => 'DE',
		'France'               => 'FR',
		'India'                => 'IN',
		'China'                => 'CN',
		'Japan'                => 'JP',
		'Brazil'               => 'BR',
		'Spain'                => 'ES',
		'Italy'                => 'IT',
		'Netherlands'          => 'NL',
		'Russia'               => 'RU',
		'Mexico'               => 'MX',
		'Sweden'               => 'SE',
		'South Korea'          => 'KR',
		'Switzerland'          => 'CH',
		'Belgium'              => 'BE',
		'Argentina'            => 'AR',
		'Austria'              => 'AT',
		'Denmark'              => 'DK',
		'Finland'              => 'FI',
		'Indonesia'            => 'ID',
		'Ireland'              => 'IE',
		'Malaysia'             => 'MY',
		'New Zealand'          => 'NZ',
		'Norway'               => 'NO',
		'Philippines'          => 'PH',
		'Poland'               => 'PL',
		'Portugal'             => 'PT',
		'Singapore'            => 'SG',
		'South Africa'         => 'ZA',
		'Thailand'             => 'TH',
		'Turkey'               => 'TR',
		'Ukraine'              => 'UA',
		'Vietnam'              => 'VN',
		'Saudi Arabia'         => 'SA',
		'United Arab Emirates' => 'AE',
		'Greece'               => 'GR',
		'Israel'               => 'IL',
		'Pakistan'             => 'PK',
		'Egypt'                => 'EG',
		'Hong Kong'            => 'HK',
		'Taiwan'               => 'TW',
		'Colombia'             => 'CO',
		'Chile'                => 'CL',
		'Czech Republic'       => 'CZ',
		'Hungary'              => 'HU',
		'Romania'              => 'RO',
		'Bangladesh'           => 'BD',
		'Nigeria'              => 'NG',
		'Morocco'              => 'MA',
		'Kenya'                => 'KE',
		'Peru'                 => 'PE',
		'Venezuela'            => 'VE',
		'Algeria'              => 'DZ',
		'Croatia'              => 'HR',
		'Bulgaria'             => 'BG',
		'Serbia'               => 'RS',
		'Slovakia'             => 'SK',
		'Slovenia'             => 'SI',
		'Lithuania'            => 'LT',
		'Latvia'               => 'LV',
		'Estonia'              => 'EE',
		'Luxembourg'           => 'LU',
		'Iceland'              => 'IS',
		'Tunisia'              => 'TN',
		'Lebanon'              => 'LB',
		'Jordan'               => 'JO',
		'Puerto Rico'          => 'PR',
		'Unknown'              => 'XX',
	);

	public static function getCountryByIP( $ip ) {
		$cache_key = CacheManager::generateTimeKey( 'PageVICO_country_' . md5( $ip ) );

		$country = CacheManager::get( $cache_key );
		if ( $country !== false ) {
			return $country;
		}

		$db_path = PageVICO_GEO_DB_PATH;

		// Check if the database file exists
		if ( ! file_exists( $db_path ) ) {
			return 'Unknown';
		}

		try {
			// Include the MaxMind library
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader.php';
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader/Decoder.php';
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader/InvalidDatabaseException.php';
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader/Metadata.php';
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader/Util.php';

			// Only check for database once per day to avoid unnecessary checks on every visit
			$last_check = get_transient( 'PageVICO_geo_db_check' );
			if ( ! $last_check ) {
				self::ensureDatabase();
				set_transient( 'PageVICO_geo_db_check', true, DAY_IN_SECONDS );
			}

			// Now try to create the reader
			$reader = new \MaxMind\Db\Reader( $db_path );
			$record = $reader->get( $ip );
			$reader->close();

			$country = $record['country']['names']['en'] ?? 'Unknown';
			CacheManager::set( $cache_key, $country, CacheManager::LONG_CACHE_DURATION );

			return $country;
		} catch ( \Exception $e ) {
			return 'Unknown';
		}
	}

	public static function getLocationDataByIP( $ip ) {
		$cache_key = CacheManager::generateTimeKey( 'PageVICO_location_' . md5( $ip ) );

		$location_data = CacheManager::get( $cache_key );
		if ( $location_data !== false ) {
			return $location_data;
		}

		$db_path = PageVICO_GEO_DB_PATH;

		// Check if the database file exists
		if ( ! file_exists( $db_path ) ) {
			return [
				'country' => 'Unknown',
				'region' => 'Unknown',
				'city' => 'Unknown',
			];
		}

		try {
			// Include the MaxMind library
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader.php';
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader/Decoder.php';
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader/InvalidDatabaseException.php';
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader/Metadata.php';
			require_once PageVICO_PLUGIN_DIR . 'includes/Geo/MaxMind/src/MaxMind/Db/Reader/Util.php';

			// Only check for database once per day to avoid unnecessary checks on every visit
			$last_check = get_transient( 'PageVICO_geo_db_check' );
			if ( ! $last_check ) {
				self::ensureDatabase();
				set_transient( 'PageVICO_geo_db_check', true, DAY_IN_SECONDS );
			}

			// Now try to create the reader
			$reader = new \MaxMind\Db\Reader( $db_path );
			$record = $reader->get( $ip );
			$reader->close();

			$location_data = [
				'country' => $record['country']['names']['en'] ?? 'Unknown',
				'region' => $record['subdivisions'][0]['names']['en'] ?? 'Unknown',
				'city' => $record['city']['names']['en'] ?? 'Unknown',
			];

			CacheManager::set( $cache_key, $location_data, CacheManager::LONG_CACHE_DURATION );

			return $location_data;
		} catch ( \Exception $e ) {
			return [
				'country' => 'Unknown',
				'region' => 'Unknown',
				'city' => 'Unknown',
			];
		}
	}

	public static function getCity( $ip ) {
		$location = self::getLocationDataByIP( $ip );
		return $location['city'];
	}

	public static function getRegion( $ip ) {
		$location = self::getLocationDataByIP( $ip );
		return $location['region'];
	}

	public static function ensureDatabase() {
		if ( ! file_exists( PageVICO_GEO_DB_PATH ) ) {
			self::downloadDatabase();
		}
	}

	public static function downloadDatabase() {
		if ( ! wp_mkdir_p( PageVICO_GEO_DB_DIR ) ) {
			return false;
		}

		$response = wp_remote_get(
			PageVICO_GEO_DB_URL,
			array(
				'timeout'  => 300,
				'stream'   => true,
				'filename' => PageVICO_GEO_DB_PATH,
			)
		);

		if ( is_wp_error( $response ) ) {
			return false;
		}

		return true;
	}

	public static function getCountryCode( $country_name ) {
		return self::$country_codes[ $country_name ] ?? null;
	}
}
