<?php
/**
 * Country Code Detection Class.
 *
 * @package automation-web-platform
 */

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

require_once WAWP_PLUGIN_DIR . 'includes/helpers/class-wawp-country-code-list.php';
require_once WAWP_PLUGIN_DIR . 'includes/helpers/class-wawp-rest-lookup-carrier.php';
if ( file_exists( WAWP_PLUGIN_DIR . 'vendor/autoload.php' ) ) {
	require_once WAWP_PLUGIN_DIR . 'vendor/autoload.php';
}

/**
 * Class WAWP_CountryCode.
 */
class WAWP_CountryCode {
	use WAWP_Security_Trait;
	use WAWP_Settings_Handler;
	use WAWP_Phone_Helper_Trait;

	/**
	 * Singleton instance.
	 *
	 * @var WAWP_CountryCode|null
	 */
	private static $instance = null;

	/**
	 * Get Singleton instance.
	 *
	 * @return WAWP_CountryCode
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * WAWP_CountryCode constructor.
	 */
	public function __construct() {
	}

	/**
	 * Get React settings data for country code detection.
	 *
	 * @return array
	 */
	public function get_react_settings_data() {
		$options = $this->get_wawp_setting( WAWP_Settings_Registry::INTL_TEL_OPTIONS, array() );
		return array(
			'settings'     => array(
				'default_country_code'   => $options['default_country_code'] ?? 'us',
				'enable_ip_detection'    => array_key_exists( 'enable_ip_detection', $options ) ? ! empty( $options['enable_ip_detection'] ) : true,
				'enabled_countries'      => $options['enabled_countries'] ?? array(),
				'country_code_alignment' => $options['country_code_alignment'] ?? 'auto',
				'enable_carrier_lookup'  => $options['enable_carrier_lookup'] ?? '1',
				'phone_fields'           => ! empty( $options['phone_fields'] ) ? $options['phone_fields'] : $this->get_default_phone_fields(),
			),
			'allCountries' => $this->get_all_countries(),
			'i18n'         => array(
				'title'                 => esc_html__( 'Advanced Country Code', 'automation-web-platform' ),
				'subtitle'              => esc_html__( 'Auto-correct customer phone numbers based on their country code.', 'automation-web-platform' ),
				'general'               => esc_html__( 'General', 'automation-web-platform' ),
				'integrations'          => esc_html__( 'Integrations', 'automation-web-platform' ),
				'allowedCountries'      => esc_html__( 'Allowed Countries', 'automation-web-platform' ),
				'defaultCountry'        => esc_html__( 'Default Country', 'automation-web-platform' ),
				'defaultCountryDesc'    => esc_html__( 'Select the country that will be selected by default.', 'automation-web-platform' ),
				'example'               => esc_html__( 'Example', 'automation-web-platform' ),
				'alignment'             => esc_html__( 'Flag Alignment', 'automation-web-platform' ),
				'alignmentDesc'         => esc_html__( 'Choose where the country flag should be positioned.', 'automation-web-platform' ),
				'alignmentRecommended'  => esc_html__( 'Recommended', 'automation-web-platform' ),
				'alignmentAuto'         => esc_html__( 'Auto', 'automation-web-platform' ),
				'alignmentLeft'         => esc_html__( 'Left', 'automation-web-platform' ),
				'alignmentRight'        => esc_html__( 'Right', 'automation-web-platform' ),
				'alignmentAutoDesc'     => esc_html__( 'Auto-detect by language', 'automation-web-platform' ),
				'alignmentLeftDesc'     => esc_html__( 'Force LTR alignment', 'automation-web-platform' ),
				'alignmentRightDesc'    => esc_html__( 'Force RTL alignment', 'automation-web-platform' ),
				'enableCarrierTitle'    => esc_html__( 'Carrier Lookup', 'automation-web-platform' ),
				'enableCarrierDesc'     => esc_html__( 'Enable real-time carrier lookup for phone numbers.', 'automation-web-platform' ),
				'carrierLookupActive'   => esc_html__( 'Carrier lookup is active.', 'automation-web-platform' ),
				'carrierLookupInactive' => esc_html__( 'Carrier lookup is inactive.', 'automation-web-platform' ),
				'enableIpTitle'         => esc_html__( 'Enable IP Detection', 'automation-web-platform' ),
				'enableIpDesc'          => esc_html__( 'Automatically detect the customer\'s country code based on their IP address.', 'automation-web-platform' ),
				'ipDetectActive'        => esc_html__( 'IP detection is active.', 'automation-web-platform' ),
				'ipDetectInactive'      => esc_html__( 'IP detection is inactive.', 'automation-web-platform' ),
				'targetFields'          => esc_html__( 'Target Fields', 'automation-web-platform' ),
				'targetFieldsDesc'      => esc_html__( 'Specify CSS selectors of the phone input fields.', 'automation-web-platform' ),
				'targetFieldsStatus'    => esc_html__( 'The following fields are being monitored.', 'automation-web-platform' ),
				'cssSelector'           => esc_html__( 'CSS Selector', 'automation-web-platform' ),
				'internalName'          => esc_html__( 'Internal Name', 'automation-web-platform' ),
				'coreFieldNote'         => esc_html__( 'This is a core field.', 'automation-web-platform' ),
				'addNewField'           => esc_html__( 'Add New Field', 'automation-web-platform' ),
				'allowedCountriesTitle' => esc_html__( 'Limit Allowed Countries', 'automation-web-platform' ),
				'allowedCountriesDesc'  => esc_html__( 'Select which countries should be available.', 'automation-web-platform' ),
				'searchCountries'       => esc_html__( 'Search countries...', 'automation-web-platform' ),
				'liveSearchPlaceholder' => esc_html__( 'Live search by country name or dial code...', 'automation-web-platform' ),
				'selectAll'             => esc_html__( 'Select All', 'automation-web-platform' ),
				'deselectAll'           => esc_html__( 'Deselect All', 'automation-web-platform' ),
				'active'                => esc_html__( 'Active', 'automation-web-platform' ),
				'inactive'              => esc_html__( 'Inactive', 'automation-web-platform' ),
				'saving'                => esc_html__( 'Saving Changes...', 'automation-web-platform' ),
				'synchronized'          => esc_html__( 'All Changes Saved', 'automation-web-platform' ),
				'unsaved'               => esc_html__( 'Unsaved Changes', 'automation-web-platform' ),
				'saveChanges'           => esc_html__( 'Save Settings', 'automation-web-platform' ),
				'selectCountry'         => esc_html__( 'Select Country', 'automation-web-platform' ),
			),
		);
	}

	/**
	 * Initialize the class hooks.
	 */
	public function init() {
		add_action( 'enqueue_block_assets', array( $this, 'enqueue_frontend_scripts' ) );
		add_filter( 'wawp_frontend_global_vars', array( $this, 'add_frontend_global_vars' ) );
		add_action( 'admin_init', array( $this, 'register_settings' ) );
	}

	/**
	 * Enqueue frontend scripts and styles.
	 */
	public function enqueue_frontend_scripts() {
		$options           = $this->get_wawp_setting( WAWP_Settings_Registry::INTL_TEL_OPTIONS, array() );
		$allowed_countries = isset( $options['enabled_countries'] ) && is_array( $options['enabled_countries'] ) ? $options['enabled_countries'] : array();
		if ( empty( $allowed_countries ) ) {
			return;
		}

		wp_enqueue_style( 'wawp-intl-tel-input-css', WAWP_PLUGIN_URL . 'assets/css/intlTelInput.css', array(), '26.9.2' );
		$bg_url    = WAWP_PLUGIN_URL . 'assets/img/flags.webp';
		$bg_url_2x = WAWP_PLUGIN_URL . 'assets/img/flags.webp';

		wp_add_inline_style(
			'wawp-intl-tel-input-css',
			" .iti__flag { background-image: url('" . esc_url( $bg_url ) . "'); }
			.iti__il { background-position: -2848px 0 !important; }
			@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
				.iti__flag { background-image: url('" . esc_url( $bg_url_2x ) . "'); }
				.iti__il { background-position: -2848px 0 !important; }
			}
			.iti.iti--allow-dropdown input { padding-top: 10px !important; padding-bottom: 10px !important; }
			.iti--flag-left input { padding-left: 55px !important; padding-right: 12px !important; text-align: left !important; }
			.iti--flag-right input { padding-right: 55px !important; padding-left: 12px !important; text-align: right !important; }
			.iti__country-container { z-index: 5 !important; }
			.iti__selected-flag { border: none !important; background: transparent !important; outline: none !important; }
			.iti, .iti input { background: transparent !important; }
			.iti input { width: 100% !important; display: block !important; }
			.iti__dropdown-content { border-radius: 12px !important; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04) !important; border: 1px solid #e5e7eb !important; margin-top: 5px !important; z-index: 99999 !important; background: #fff !important; }
			.iti__search-input { padding: 12px 15px !important; border: none !important; border-bottom: 1px solid #f3f4f6 !important; border-radius: 0 !important; font-size: 14px !important; outline: none !important; }
			.iti__country { padding: 10px 15px !important; outline: none !important; }
			.iti__country-name { font-size: 14px !important; color: #374151 !important; }
			.iti__dial-code { color: #9ca3af !important; font-size: 13px !important; }
			.iti--flag-right .iti__dropdown-content { text-align: right !important; direction: rtl !important; }
			.iti--flag-right .iti__country { display: flex !important; flex-direction: row !important; justify-content: flex-start !important; gap: 10px !important; }
			.iti--flag-right .iti__flag-box { margin-left: 0 !important; margin-right: 0 !important; }
			"
		);

		wp_enqueue_script( 'wawp-intl-tel-input-js', WAWP_PLUGIN_URL . 'assets/js/resources/intlTelInput.min.js', array(), '26.9.2', true );
		wp_enqueue_script( 'wawp-intl-tel-input-utils-js', WAWP_PLUGIN_URL . 'assets/js/resources/utils.js', array( 'wawp-intl-tel-input-js' ), '26.9.2', true );

		wp_enqueue_script( 'wawp-country-code-script', WAWP_PLUGIN_URL . 'assets/js/block-checkout-intl-tel.js', array( 'wawp-intl-tel-input-js', 'jquery' ), WAWP_PLUGIN_VERSION, true );
	}

	/**
	 * Add global variables to the central data hub.
	 *
	 * @param array $vars Global variables array.
	 * @return array
	 */
	public function add_frontend_global_vars( $vars ) {
		$options           = $this->get_wawp_setting( WAWP_Settings_Registry::INTL_TEL_OPTIONS, array() );
		$allowed_countries = isset( $options['enabled_countries'] ) && is_array( $options['enabled_countries'] ) ? $options['enabled_countries'] : array();

		// Filter out invalid country codes that cause intl-tel-input warnings.
		$invalid_countries = array( 'aq', 'bv', 'gs', 'hm', 'pn', 'tf', 'um' );
		$allowed_countries = array_values( array_diff( $allowed_countries, $invalid_countries ) );

		if ( empty( $allowed_countries ) ) {
			return $vars;
		}

		$default               = ! empty( $options['default_country_code'] ) ? $options['default_country_code'] : 'us';
		$enable_carrier_lookup = array_key_exists( 'enable_carrier_lookup', $options ) ? ! empty( $options['enable_carrier_lookup'] ) : true;
		$enable_ip_detection   = array_key_exists( 'enable_ip_detection', $options ) ? ! empty( $options['enable_ip_detection'] ) : true;

		$default_fields = $this->get_default_phone_fields();

		$phone_fields = array();
		if ( ! empty( $options['phone_fields'] ) && is_array( $options['phone_fields'] ) ) {
			foreach ( $options['phone_fields'] as $f ) {
				if ( isset( $f['enabled'] ) && '1' === $f['enabled'] && ! empty( $f['id'] ) ) {
					if ( '#wawp_whatsapp' === $f['id'] ) {
						continue;
					}
					$phone_fields[] = array(
						'id'      => $f['id'],
						'name'    => isset( $f['name'] ) ? $f['name'] : '',
						'enabled' => '1',
					);
				}
			}
		}

		$active_ids = array_map(
			function ( $f ) {
				return $f['id'];
			},
			$phone_fields
		);
		foreach ( $default_fields as $df ) {
			if ( ! in_array( $df['id'], $active_ids, true ) ) {
				$phone_fields[] = $df;
			}
		}

		$self             = $this;
		$saved_phone_func = function () use ( $self ) {
			$phone   = '';
			$user_id = get_current_user_id();
			if ( $user_id ) {
				$phone = (string) WAWP()->user_manager->get_user_phone( $user_id );
			}

			if ( empty( $phone ) ) {
				$client_ip = $self->get_client_ip();
				$cache_key = 'wawp_saved_phone_' . md5( $client_ip );
				$phone     = (string) wp_cache_get( $cache_key, 'wawp_security' );
			}

			return self::get_digits_only( $phone );
		};

		$autofill_func = function () {
			return (int) $this->get_wawp_setting( WAWP_Settings_Registry::AC_POPUP_AUTOFILL_FRONTEND, 1 );
		};

		$vars['wawpIntlTelSettings'] = array(
			'defaultCountry'        => $default ? $default : 'us',
			'phoneFields'           => $phone_fields,
			'allowedCountries'      => $allowed_countries,
			'countryCodeAlignment'  => isset( $options['country_code_alignment'] ) ? $options['country_code_alignment'] : 'auto',
			'isRTL'                 => is_rtl(),
			'locale'                => str_replace( '_', '-', get_locale() ),
			'utilsUrl'              => WAWP_PLUGIN_URL . 'assets/js/resources/utils.js',
			'lookupCarrierEndpoint' => rest_url( 'wawp/v2/lookup-carrier' ),
			'enableCarrierLookup'   => $enable_carrier_lookup,
			'enableIpDetection'     => $enable_ip_detection,
			'detectedCountry'       => $this->get_client_country_by_ip(),
			'savedPhone'            => $saved_phone_func(),
			'autofillFrontend'      => $autofill_func(),
		);

		$vars['wawpAllCountries'] = $this->get_all_countries();

		$vars['wawpTelInputStrings'] = array(
			'valid'             => esc_html__( '✓ Valid phone number.', 'automation-web-platform' ),
			'invalid'           => esc_html__( '✗ Invalid phone number.', 'automation-web-platform' ),
			'searchPlaceholder' => esc_html__( 'Search country', 'automation-web-platform' ),
			'waiting'           => esc_html__( 'Number updates automatically after writing.', 'automation-web-platform' ),
			'waExists'          => esc_html__( 'WhatsApp found', 'automation-web-platform' ),
			'waNotFound'        => esc_html__( 'WhatsApp not found', 'automation-web-platform' ),
			'delete'            => esc_html__( 'Delete', 'automation-web-platform' ),
		);

		return $vars;
	}

	/**
	 * Register settings for country code detection.
	 */
	public function register_settings() {
		register_setting(
			'woo_intl_tel_options_group',
			WAWP_Settings_Registry::INTL_TEL_OPTIONS,
			array(
				'type'              => 'array',
				'sanitize_callback' => array( $this, 'sanitize_options' ),
			)
		);
	}

	/**
	 * Sanitize options callback.
	 *
	 * @param array $opts Options array.
	 * @return array
	 */
	public function sanitize_options( $opts ) {
		if ( ! is_array( $opts ) ) {
			return is_string( $opts ) ? sanitize_text_field( $opts ) : array();
		}

		$sanitized = array();

		// Sanitize known arrays and keys.
		if ( isset( $opts['default_country_code'] ) ) {
			$sanitized['default_country_code'] = sanitize_key( $opts['default_country_code'] );
		}

		if ( isset( $opts['enabled_countries'] ) && is_array( $opts['enabled_countries'] ) ) {
			$sanitized['enabled_countries'] = array_map( 'sanitize_key', $opts['enabled_countries'] );
		}

		if ( isset( $opts['phone_fields'] ) && is_array( $opts['phone_fields'] ) ) {
			$sanitized['phone_fields'] = array_map( 'sanitize_text_field', $opts['phone_fields'] );
		}

		// Sanitize any remaining fields to prevent data loss while ensuring security.
		foreach ( $opts as $key => $value ) {
			if ( ! isset( $sanitized[ $key ] ) ) {
				if ( is_array( $value ) ) {
					$sanitized[ $key ] = array_map( 'sanitize_text_field', $value );
				} else {
					$sanitized[ $key ] = sanitize_text_field( $value );
				}
			}
		}

		return $sanitized;
	}

	/**
	 * Convert ISO2 country code to emoji flag.
	 *
	 * @param string $iso ISO2 code.
	 * @return string
	 */
	private function iso2_to_flag( $iso ) {
		$iso  = strtoupper( $iso );
		$flag = '';
		$len  = mb_strlen( $iso );
		for ( $i = 0; $i < $len; $i++ ) {
			$code  = 127397 + ord( $iso[ $i ] );
			$flag .= mb_convert_encoding( '&#' . $code . ';', 'UTF-8', 'HTML-ENTITIES' );
		}
		return $flag;
	}

	/**
	 * Get all supported countries.
	 *
	 * @return array
	 */
	private function get_all_countries() {
		if ( function_exists( 'WAWP\wawp_get_all_countries' ) ) {
			return \WAWP\wawp_get_all_countries();
		}
		return array(
			array(
				'iso2'   => 'us',
				'name'   => esc_html__( 'United States', 'automation-web-platform' ),
				'region' => esc_html__( 'Americas', 'automation-web-platform' ),
			),
			array(
				'iso2'   => 'eg',
				'name'   => esc_html__( 'Egypt', 'automation-web-platform' ),
				'region' => esc_html__( 'Middle East', 'automation-web-platform' ),
			),
		);
	}
	/**
	 * Get default phone fields for monitoring.
	 *
	 * @return array
	 */
	private function get_default_phone_fields() {
		return array(
			array(
				'id'      => '#billing-phone',
				'name'    => 'Woocommerce Gutenberg React',
				'enabled' => '1',
			),
			array(
				'id'      => '#billing_phone',
				'name'    => 'Normal Woocommerce Checkout',
				'enabled' => '1',
			),
			array(
				'id'      => '#wawp_phone',
				'name'    => 'Wawp Login & Signup Forms',
				'enabled' => '1',
			),
			array(
				'id'      => '#billing_phone_popup',
				'name'    => 'Abandoned Cart Popup',
				'enabled' => '1',
			),
		);
	}

	/**
	 * Get client's country code by IP.
	 *
	 * @return string ISO2 country code (lowercase).
	 */
	public function get_client_country_by_ip() {
		// 1. Check Cloudflare header
		if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) {
			return strtolower( sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) );
		}

		// 2. Check other common geo headers
		$headers = array(
			'HTTP_X_COUNTRY_CODE',
			'HTTP_X_REAL_IP_COUNTRY',
			'HTTP_GEOIP_COUNTRY_CODE',
			'HTTP_GEOIP_COUNTRY',
			'HTTP_X_GEOIP_COUNTRY',
		);
		foreach ( $headers as $header ) {
			if ( ! empty( $_SERVER[ $header ] ) ) {
				return strtolower( sanitize_text_field( wp_unslash( $_SERVER[ $header ] ) ) );
			}
		}

		// 3. WooCommerce Geolocate fallback
		if ( class_exists( 'WC_Geolocate' ) ) {
			$ip        = $this->get_client_ip();
			$geolocate = WC_Geolocate::geolocate_ip( $ip );
			if ( ! empty( $geolocate['country'] ) ) {
				return strtolower( $geolocate['country'] );
			}
		}

		// 4. External API (like ipapi.co) using transient cache to avoid slowing down requests
		$ip = $this->get_client_ip();
		if ( ! empty( $ip ) && '127.0.0.1' !== $ip && '::1' !== $ip ) {
			$cache_key = 'wawp_ip_country_' . md5( $ip );
			$country   = get_transient( $cache_key );
			if ( false === $country ) {
				$response = wp_remote_get( 'https://ipapi.co/' . $ip . '/country/' );
				if ( ! is_wp_error( $response ) && 200 === wp_remote_retrieve_response_code( $response ) ) {
					$country = trim( wp_remote_retrieve_body( $response ) );
					if ( 2 === strlen( $country ) ) {
						$country = strtolower( $country );
						set_transient( $cache_key, $country, DAY_IN_SECONDS );
					} else {
						$country = '';
					}
				} else {
					$country = '';
				}
			}
			if ( ! empty( $country ) ) {
				return $country;
			}
		}

		return '';
	}
}
