<?php

namespace FleekDash\Services\AnalyticsTracking;

final class TrackingRequestRuntime
{
    /**
     * @param array<string, mixed> $settings
     * @return array{respectDnt: bool, trackLoggedIn: bool, ignoreRoles: array<int, string>, excludedUserAgents: array<int, string>, anonymizeIp: bool}
     */
    public static function buildTrackingRules(array $settings): array
    {
        $ignoreRoles = [];
        if (isset($settings['ignore_roles']) && \is_array($settings['ignore_roles'])) {
            $ignoreRoles = $settings['ignore_roles'];
        } elseif (isset($settings['ignore_roles']) && \is_string($settings['ignore_roles'])) {
            $ignoreRoles = \array_filter(\array_map('trim', \explode(',', $settings['ignore_roles'])));
        }

        $excludedUserAgents = [];
        if (isset($settings['excluded_user_agents'])) {
            $excludedUserAgents = \preg_split('/\r\n|\r|\n/', (string) $settings['excluded_user_agents']) ?: [];
        }

        return [
            'respectDnt' => !empty($settings['respect_dnt']),
            'trackLoggedIn' => !empty($settings['track_logged_in']),
            'ignoreRoles' => \array_values($ignoreRoles),
            'excludedUserAgents' => \array_values($excludedUserAgents),
            'anonymizeIp' => !empty($settings['anonymize_ip']),
        ];
    }

    /**
     * @param array{respectDnt: bool, trackLoggedIn: bool, ignoreRoles: array<int, string>, excludedUserAgents: array<int, string>, anonymizeIp: bool} $trackingRules
     */
    public static function shouldSkipTracking(array $trackingRules): bool
    {
        $dntEnabled = $trackingRules['respectDnt']
            && isset($_SERVER['HTTP_DNT'])
            && $_SERVER['HTTP_DNT'] === '1';
        $skipLoggedInUsers = !$trackingRules['trackLoggedIn'] && \is_user_logged_in();
        $blockedByRole = !self::isRoleAllowedForTracking($trackingRules['ignoreRoles']);
        $blockedByUserAgent = self::isUserAgentExcluded($trackingRules['excludedUserAgents']);

        return $dntEnabled || $skipLoggedInUsers || $blockedByRole || $blockedByUserAgent;
    }

    private static function anonymizeIpv4(string $ipAddress): string
    {
        $parts = \explode('.', $ipAddress);
        $parts[\count($parts) - 1] = '0';
        return \implode('.', $parts);
    }

    public static function anonymizeIpAddress(string $ipAddress, bool $anonymizeIp): string
    {
        $normalizedIp = $ipAddress;
        if ($anonymizeIp && $ipAddress !== '') {
            if (\filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                $normalizedIp = self::anonymizeIpv4($ipAddress);
            } elseif (\filter_var($ipAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                $normalizedIp = (string) \preg_replace('/:[0-9a-f]{1,4}$/i', ':0000', $ipAddress);
            }
        }
        return $normalizedIp;
    }

    public static function getAggregationStepModifier(string $aggregation): string
    {
        $stepModifier = '+1 day';
        if ($aggregation === 'weekly') {
            $stepModifier = '+7 days';
        } elseif ($aggregation === 'monthly') {
            $stepModifier = '+1 month';
        }
        return $stepModifier;
    }

    /**
     * @param array<int, string> $ignoreRoles
     */
    private static function isRoleAllowedForTracking(array $ignoreRoles): bool
    {
        $allowed = true;
        if (!empty($ignoreRoles) && \is_user_logged_in()) {
            $user = \wp_get_current_user();
            if ($user && $user->ID > 0) {
                $userRoles = $user->roles ?? [];
                foreach ($userRoles as $role) {
                    if (\in_array($role, $ignoreRoles, true)) {
                        $allowed = false;
                        break;
                    }
                }
            }
        }
        return $allowed;
    }

    /**
     * @param array<int, string> $excludedUserAgents
     */
    private static function isUserAgentExcluded(array $excludedUserAgents): bool
    {
        $excluded = false;
        if (!empty($excludedUserAgents)) {
            $ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
            foreach ($excludedUserAgents as $needle) {
                $needle = \trim($needle);
                if ($needle !== '' && \stripos($ua, $needle) !== false) {
                    $excluded = true;
                    break;
                }
            }
        }
        return $excluded;
    }
}
