<?php
namespace PageVICO\Tracking;

defined( 'ABSPATH' ) || exit;

class TrackingConditions {
	/**
	 * Check if tracking should proceed based on all conditions
	 */
	public static function shouldTrack() {
		// Check if tracking is enabled globally
		if ( ! \get_option( 'PageVICO_enable_tracking', 1 ) ) {
			return false;
		}

		// Check blocked IPs first (most restrictive)
		if ( ! self::isAllowedIP() ) {
			return false;
		}

		// Check if current user is blocked
		if ( ! self::isAllowedUser() ) {
			return false;
		}

		// Check if current user role is allowed
		if ( ! self::isAllowedUserRole() ) {
			return false;
		}

		return true;
	}

	/**
	 * Check if current user is not blocked
	 */
	private static function isAllowedUser() {
		if ( ! function_exists( 'wp_get_current_user' ) ) {
			require_once ABSPATH . 'wp-includes/pluggable.php';
		}

		// Ensure user is initialized (especially in REST or custom entry points)
		if ( ! function_exists( 'wp_get_current_user' ) || ! function_exists( 'get_current_user_id' ) ) {
			return true;
		}

		$user = \wp_get_current_user();

		if ( ! $user || ! $user->exists() ) {
			return true; // Allow tracking for non-logged-in users
		}

		$blocked_users = (array) \get_option( 'PageVICO_block_users', array() );
		if ( empty( $blocked_users ) ) {
			return true;
		}

		return ! in_array( $user->user_login, $blocked_users, true );
	}

	/**
	 * Check if current IP is not blocked
	 */
	private static function isAllowedIP() {
		$ip = self::getClientIP();

		$blocked_ips = \get_option( 'PageVICO_block_ips', '' );

		if ( empty( $blocked_ips ) ) {
			return true;
		}

		// Split blocked IPs by newline
		$blocked_list = array_filter( array_map( 'trim', explode( "\n", $blocked_ips ) ) );

		foreach ( $blocked_list as $blocked ) {
			if ( empty( $blocked ) ) {
				continue;
			}

			// Check exact IP match
			if ( $blocked === $ip ) {
				return false;
			}

			// Check CIDR range
			if ( strpos( $blocked, '/' ) !== false && self::isValidCIDR( $blocked ) ) {
				if ( self::ipInCIDR( $ip, $blocked ) ) {
					return false;
				}
			}

			// Check IP range
			if ( strpos( $blocked, '-' ) !== false ) {
				if ( self::ipInRange( $ip, $blocked ) ) {
					return false;
				}
			}
		}

		return true;
	}

	/**
	 * Validate CIDR notation
	 */
	private static function isValidCIDR( $cidr ) {
		$parts = explode( '/', $cidr );
		if ( count( $parts ) !== 2 ) {
			return false;
		}

		$ip   = $parts[0];
		$bits = intval( $parts[1] );

		return filter_var( $ip, FILTER_VALIDATE_IP ) && $bits >= 0 && $bits <= 32;
	}

	/**
	 * Check if IP is in CIDR range
	 */
	private static function ipInCIDR( $ip, $cidr ) {
		list($subnet, $bits) = explode( '/', $cidr );

		$ip     = ip2long( $ip );
		$subnet = ip2long( $subnet );

		if ( $ip === false || $subnet === false ) {
			return false;
		}

		$mask    = -1 << ( 32 - $bits );
		$subnet &= $mask;

		return ( $ip & $mask ) == $subnet;
	}

	/**
	 * Check if IP is in range
	 */
	private static function ipInRange( $ip, $range ) {
		list($start, $end) = explode( '-', $range );
		$start             = trim( $start );
		$end               = trim( $end );

		$ip    = ip2long( $ip );
		$start = ip2long( $start );
		$end   = ip2long( $end );

		if ( $ip === false || $start === false || $end === false ) {
			return false;
		}

		return ( $ip >= $start && $ip <= $end );
	}

	/**
     * Get client IP address
     */
    private static function getClientIP() {
		
        // Get the raw IP address from server variables
        $ip = isset($_SERVER['HTTP_CLIENT_IP']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_CLIENT_IP'])) : null;
        $ip = $ip ?: (isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_X_FORWARDED_FOR'])) : null);
        $ip = $ip ?: (isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '0.0.0.0');

        // If multiple IPs are present, take the first one
        if (strpos($ip, ',') !== false) {
            $ips = explode(',', $ip);
            $ip  = trim($ips[0]);
        }

        // Sanitize the IP
        $ip = sanitize_text_field($ip);

        // Final validation
        return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '0.0.0.0';
    }


	/**
	 * Check if current user role is allowed
	 */
	private static function isAllowedUserRole() {
		$blocked_roles = (array) \get_option( 'PageVICO_exclude_roles', array() );

		if ( empty( $blocked_roles ) ) {
			return true;
		}

		$user = wp_get_current_user();
		if ( ! $user->exists() ) {
			return true; // Allow tracking for non-logged in users
		}

		foreach ( $user->roles as $role ) {
			if ( in_array( $role, $blocked_roles ) ) {
				return false;
			}
		}

		return true;
	}
}
