<?php

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

class Sabriel_Helpers {

	const DOMINI_USA_E_GETTA = [
		'10minutemail.com', '10minutemail.net', '20minutemail.com', 'guerrillamail.com',
		'cazlp.com', 'gonrr.net', 'jbsze.com', 'jbsze.net',
		'kjkpc.net', 'onldm.net', 'vtmpj.com', 'vtmpj.net',
		'guerrillamail.info', 'guerrillamail.biz', 'guerrillamail.de', 'guerrillamail.net',
		'guerrillamail.org', 'mailinator.com', 'mailinator.net', 'mailinator2.com',
		'tempmail.com', 'temp-mail.org', 'temp-mail.io', 'tempmail.net',
		'yopmail.com', 'yopmail.fr', 'yopmail.net', 'throwawaymail.com',
		'sharklasers.com', 'trashmail.com', 'trashmail.me', 'trashmail.net',
		'maildrop.cc', 'getnada.com', 'dispostable.com', 'fakeinbox.com',
		'mohmal.com', 'emailondeck.com', 'mintemail.com', 'mailnesia.com',
		'mailcatch.com', 'mailsac.com', 'burnermail.io', 'discard.email',
		'spamgourmet.com', 'moakt.com', 'tempinbox.com', 'fakemailgenerator.com',
		'generator.email', 'emkei.cz', 'mytemp.email', 'tempm.com',
		'33mail.com', 'mailnull.com', 'spam4.me', 'mailexpire.com',
		'tempr.email', 'tmailor.com', 'mailpoof.com', 'byom.de',
		'wegwerfemailadresse.com',
	];

	public static function domini_usa_e_getta() {
		return self::DOMINI_USA_E_GETTA;
	}

	public static function email_temporanea( $email ) {
		$pos = strrpos( (string) $email, '@' );
		if ( false === $pos ) {
			return false;
		}
		$dominio = strtolower( trim( substr( (string) $email, $pos + 1 ) ) );
		return in_array( $dominio, self::DOMINI_USA_E_GETTA, true );
	}

	public static function email_pulita( $valore ) {
		return is_scalar( $valore ) ? sanitize_email( (string) $valore ) : '';
	}

	public static function e_una_post() {
		if ( ! isset( $_SERVER['REQUEST_METHOD'] ) ) {
			return false;
		}
		return 'POST' === strtoupper( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) );
	}

	public static function get_client_ip() {
		$remoto = isset( $_SERVER['REMOTE_ADDR'] ) ? trim( sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) ) : '';

		if ( ! empty( $_SERVER['HTTP_CF_CONNECTING_IP'] ) && self::proxy_attendibile( $remoto ) ) {
			$vero = trim( sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) );
			if ( filter_var( $vero, FILTER_VALIDATE_IP ) ) {
				return $vero;
			}
		}

		return filter_var( $remoto, FILTER_VALIDATE_IP ) ? $remoto : '0.0.0.0';
	}

	private static function proxy_attendibile( $ip ) {
		if ( '' === $ip ) {
			return false;
		}
		$range = [

			'173.245.48.0/20', '103.21.244.0/22', '103.22.200.0/22', '103.31.4.0/22',
			'141.101.64.0/18', '108.162.192.0/18', '190.93.240.0/20', '188.114.96.0/20',
			'197.234.240.0/22', '198.41.128.0/17', '162.158.0.0/15', '104.16.0.0/13',
			'104.24.0.0/14', '172.64.0.0/13', '131.0.72.0/22',

			'2400:cb00::/32', '2606:4700::/32', '2803:f800::/32', '2405:b500::/32',
			'2405:8100::/32', '2a06:98c0::/29', '2c0f:f248::/32',
		];

		$range = apply_filters( 'sabriel_ai_range_proxy_attendibili', $range );

		foreach ( (array) $range as $cidr ) {
			if ( self::ip_dentro_cidr( $ip, (string) $cidr ) ) {
				return true;
			}
		}
		return false;
	}

	public static function ip_dentro_cidr( $ip, $cidr ) {

		if ( 0 === stripos( $ip, '::ffff:' ) && filter_var( substr( $ip, 7 ), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
			$ip = substr( $ip, 7 );
		}
		if ( false === strpos( $cidr, '/' ) ) {
			return $ip === $cidr;
		}
		list( $rete, $bit ) = explode( '/', $cidr, 2 );
		$bit      = (int) $bit;
		$ip_bin   = @inet_pton( $ip );
		$rete_bin = @inet_pton( $rete );

		if ( false === $ip_bin || false === $rete_bin || strlen( $ip_bin ) !== strlen( $rete_bin ) ) {
			return false;
		}
		if ( $bit < 0 || $bit > strlen( $ip_bin ) * 8 ) {
			return false;
		}
		$byte_interi = intdiv( $bit, 8 );
		$bit_avanzo  = $bit % 8;
		if ( $byte_interi > 0 && substr( $ip_bin, 0, $byte_interi ) !== substr( $rete_bin, 0, $byte_interi ) ) {
			return false;
		}
		if ( 0 === $bit_avanzo ) {
			return true;
		}
		$maschera = chr( ( 0xFF << ( 8 - $bit_avanzo ) ) & 0xFF );
		return ( $ip_bin[ $byte_interi ] & $maschera ) === ( $rete_bin[ $byte_interi ] & $maschera );
	}

	public static function now() {
		return new DateTime( 'now', wp_timezone() );
	}

	public static function nome_lingua_bot() {
		$nomi = [
			'it' => 'Italian', 'en' => 'English', 'es' => 'Spanish', 'fr' => 'French',
			'de' => 'German', 'pt' => 'Portuguese', 'nl' => 'Dutch', 'ru' => 'Russian',
			'id' => 'Indonesian',
		];
		$codice = 'it';
		if ( class_exists( 'Sabriel_Module_Settings' ) && method_exists( 'Sabriel_Module_Settings', 'bot_lingua_con_rilevamento' ) ) {
			$codice = (string) Sabriel_Module_Settings::bot_lingua_con_rilevamento();
		}
		return $nomi[ $codice ] ?? $nomi['it'];
	}

	public static function firma_token( $materiale ) {
		return hash_hmac( 'sha256', (string) $materiale, wp_salt( 'auth' ) );
	}

	public static function firma_token_valida( $materiale, $token ) {
		if ( ! is_string( $token ) || '' === $token ) {
			return false;
		}
		if ( hash_equals( self::firma_token( $materiale ), $token ) ) {
			return true;
		}
		if ( defined( 'AUTH_KEY' ) && '' !== (string) AUTH_KEY
			&& hash_equals( hash_hmac( 'sha256', (string) $materiale, AUTH_KEY ), $token ) ) {
			return true;
		}
		return false;
	}

	const FRENO_INDICE      = 'sabriel_ai_freni_attivi';
	const FRENO_INDICE_MAX  = 5000;

	public static function freno_ricorda_chiave( $chiave, $durata ) {
		$indice = get_option( self::FRENO_INDICE, [] );
		if ( ! is_array( $indice ) ) {
			$indice = [];
		}
		$adesso = time();
		if ( isset( $indice[ $chiave ] ) && $indice[ $chiave ] > $adesso ) {
			return;
		}
		foreach ( $indice as $k => $scade ) {
			if ( (int) $scade <= $adesso ) {
				unset( $indice[ $k ] );
			}
		}
		if ( count( $indice ) >= self::FRENO_INDICE_MAX ) {
			asort( $indice );
			$indice = array_slice( $indice, (int) ( self::FRENO_INDICE_MAX / 2 ), null, true );
		}
		$indice[ $chiave ] = $adesso + max( 1, (int) $durata );
		update_option( self::FRENO_INDICE, $indice, false );
	}

	public static function freno_azzera( $prefissi ) {
		global $wpdb;
		$prefissi = (array) $prefissi;
		$tolti    = 0;

		$indice = get_option( self::FRENO_INDICE, [] );
		if ( is_array( $indice ) && $indice ) {
			foreach ( array_keys( $indice ) as $chiave ) {
				foreach ( $prefissi as $p ) {
					if ( 0 === strpos( $chiave, $p ) ) {
						delete_transient( $chiave );
						unset( $indice[ $chiave ] );
						$tolti++;
						break;
					}
				}
			}
			update_option( self::FRENO_INDICE, $indice, false );
		}

		if ( wp_using_ext_object_cache() ) {
			return $tolti;
		}

		$righe = 0;
		foreach ( $prefissi as $p ) {
			$nomi = $wpdb->get_col( $wpdb->prepare(
				"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s LIMIT %d",
				$wpdb->esc_like( '_transient_' . $p ) . '%',
				self::FRENO_INDICE_MAX
			) );
			foreach ( (array) $nomi as $nome ) {
				delete_transient( substr( (string) $nome, strlen( '_transient_' ) ) );
				$righe++;
			}
		}
		return $tolti + $righe;
	}

	public static function lingua_html() {
		$locale = function_exists( 'determine_locale' ) ? determine_locale() : get_locale();
		return str_replace( '_', '-', (string) $locale );
	}

	public static function minuscolo( $testo ) {
		$testo = (string) $testo;
		return function_exists( 'mb_strtolower' ) ? mb_strtolower( $testo, 'UTF-8' ) : strtolower( $testo );
	}

	public static function maiuscolo( $testo ) {
		$testo = (string) $testo;
		return function_exists( 'mb_strtoupper' ) ? mb_strtoupper( $testo, 'UTF-8' ) : strtoupper( $testo );
	}

	public static function intestazione_mittente( $nome, $indirizzo ) {
		$indirizzo = sanitize_email( (string) $indirizzo );
		if ( ! $indirizzo || ! is_email( $indirizzo ) ) {
			return '';
		}
		$nome = self::testo_una_riga( $nome );
		$nome = str_replace( [ '"', '<', '>', '\\' ], '', $nome );
		$nome = trim( $nome );
		if ( '' === $nome ) {
			return 'From: ' . $indirizzo;
		}
		return 'From: "' . $nome . '" <' . $indirizzo . '>';
	}

	public static function testo_una_riga( $testo ) {
		$testo = (string) $testo;
		$testo = str_replace( [ "\r", "\n", "\t" ], ' ', $testo );
		$testo = trim( (string) preg_replace( '/\s+/u', ' ', $testo ) );
		return function_exists( 'mb_substr' ) ? mb_substr( $testo, 0, 200 ) : substr( $testo, 0, 200 );
	}
}
