<?php

namespace App\Services;

use App\Models\DnsZoneStatistic;
use App\Models\Nameserver;
use App\Jobs\ProcessGeographicDistributionJob;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;

class DnsStatisticsService
{
    public function collectStatisticsForDomain($dnsZone, $date = null, $nameservers = null)
    {
        if (!$date) {
            $date = Carbon::now()->format('Y-m-d');
        }

        $statisticsCreated = 0;
        $errors = 0;

        // Dacă nu sunt furnizate nameservere, folosește nameserverele permise în planul utilizatorului
        if ($nameservers === null) {
            $user = $dnsZone->user;
            $plan = $user->plan ?? $user->resellerPlan;

            if ($plan) {
                $allowedNameServers = $plan->getAllowedNameServers();

                // Obține nameserverele active care sunt permise în plan
                $nameservers = Nameserver::where('is_active', true)
                    ->when(!empty($allowedNameServers), function($query) use ($allowedNameServers) {
                        return $query->whereIn('id', $allowedNameServers);
                    })
                    ->get();

                Log::info("Collecting statistics for zone {$dnsZone->domain} from plan-allowed nameservers", [
                    'zone' => $dnsZone->domain,
                    'plan' => $plan->name,
                    'allowed_nameservers' => $allowedNameServers,
                    'active_nameservers' => $nameservers->pluck('name')->toArray()
                ]);
            } else {
                // Fallback: folosește nameserver-ul atribuit zonei
                $nameserver = $dnsZone->nameServer;
                if (!$nameserver) {
                    Log::warning("Zone {$dnsZone->domain} has no assigned nameserver and user has no plan");
                    return [
                        'statistics_created' => 0,
                        'errors' => 1,
                        'message' => 'No nameserver assigned to zone and no plan configured'
                    ];
                }
                $nameservers = collect([$nameserver]);
            }
        }

        // Colectează și agregă statistici de pe toate nameserverele
        $aggregatedStats = [
            'total_queries' => 0,
            'cache_hits' => 0,
            'cache_misses' => 0,
            'hourly_queries' => array_fill(0, 24, 0),
            'subdomains' => [],
            'query_types' => [],
            'client_ips' => [],
            'protocols' => ['udp' => 0, 'tcp' => 0, 'ipv4' => 0, 'ipv6' => 0],
            'nameservers_data' => [],
            // Statistici globale pentru calcul proporțional
            'global_total_queries' => 0,
            'global_servfail' => 0,
            'global_nxdomain' => 0,
            'global_noerror' => 0,
            'avg_latency' => 0,
            'latency_samples' => 0,
            // ✨ DNSSEC Statistics
            'dnssec' => [
                'signatures' => 0,
                'do_queries' => 0,
                'dnskey_queries' => 0
            ],
            // ✨ Rate Limiting / Security Statistics
            'security' => [
                'overload_drops' => 0,
                'timedout_packets' => 0,
                'corrupt_packets' => 0,
                'unauth_packets' => 0,
                'recursive_queries' => 0
            ]
        ];

        foreach ($nameservers as $nameserver) {
            try {
                $stats = $this->collectFromNameserver($nameserver, $dnsZone->domain, $date);
                if ($stats) {
                    $statisticsCreated++;

                    // Agregă datele
                    if (isset($stats['zone_specific'])) {
                        $zoneStats = $stats['zone_specific'];

                        $queriesFromThisNS = $zoneStats['total_queries'] ?? 0;
                        Log::info("📊 Nameserver {$nameserver->name} returned {$queriesFromThisNS} queries for {$dnsZone->domain}");

                        $aggregatedStats['total_queries'] += $queriesFromThisNS;
                        $aggregatedStats['cache_hits'] += $zoneStats['cache_hits'] ?? 0;
                        $aggregatedStats['cache_misses'] += $zoneStats['cache_misses'] ?? 0;

                        // Agregă hourly queries
                        if (isset($zoneStats['hourly_queries'])) {
                            for ($i = 0; $i < 24; $i++) {
                                $aggregatedStats['hourly_queries'][$i] += $zoneStats['hourly_queries'][$i] ?? 0;
                            }
                        }

                        // Agregă subdomenii
                        if (isset($zoneStats['subdomains'])) {
                            foreach ($zoneStats['subdomains'] as $subdomain => $count) {
                                if (!isset($aggregatedStats['subdomains'][$subdomain])) {
                                    $aggregatedStats['subdomains'][$subdomain] = 0;
                                }
                                $aggregatedStats['subdomains'][$subdomain] += $count;
                            }
                        }

                        // Agregă protocoale
                        if (isset($zoneStats['protocols'])) {
                            foreach ($zoneStats['protocols'] as $proto => $count) {
                                $aggregatedStats['protocols'][$proto] += $count;
                            }
                        }

                        // Agregă query types
                        if (isset($zoneStats['query_types'])) {
                            foreach ($zoneStats['query_types'] as $type => $count) {
                                if (!isset($aggregatedStats['query_types'][$type])) {
                                    $aggregatedStats['query_types'][$type] = 0;
                                }
                                $aggregatedStats['query_types'][$type] += $count;
                            }
                        }

                        // Agregă client IPs
                        if (isset($zoneStats['client_ips'])) {
                            foreach ($zoneStats['client_ips'] as $ip => $count) {
                                if (!isset($aggregatedStats['client_ips'][$ip])) {
                                    $aggregatedStats['client_ips'][$ip] = 0;
                                }
                                $aggregatedStats['client_ips'][$ip] += $count;
                            }
                        }

                        $aggregatedStats['nameservers_data'][] = [
                            'nameserver' => $nameserver->name,
                            'queries' => $zoneStats['total_queries'] ?? 0
                        ];
                    }

                    // Agregă statisticile globale pentru calcul proporțional SERVFAIL/NXDOMAIN
                    if (isset($stats['general'])) {
                        $generalStats = $stats['general'];
                        $aggregatedStats['global_total_queries'] += $generalStats['total_queries'] ?? 0;
                        $aggregatedStats['global_servfail'] += $generalStats['servfail_responses'] ?? 0;
                        $aggregatedStats['global_nxdomain'] += $generalStats['nxdomain_responses'] ?? 0;
                        $aggregatedStats['global_noerror'] += $generalStats['noerror_responses'] ?? 0;

                        // Calculează media latency
                        if (isset($generalStats['latency']) && $generalStats['latency'] > 0) {
                            $aggregatedStats['avg_latency'] += $generalStats['latency'];
                            $aggregatedStats['latency_samples']++;
                        }

                        // ✨ Agregă DNSSEC statistics
                        $aggregatedStats['dnssec']['signatures'] += $generalStats['dnssec_signatures'] ?? 0;
                        $aggregatedStats['dnssec']['do_queries'] += $generalStats['dnssec_do_queries'] ?? 0;
                        $aggregatedStats['dnssec']['dnskey_queries'] += $generalStats['dnssec_dnskey_queries'] ?? 0;

                        // ✨ Agregă Security / Rate Limiting statistics
                        $aggregatedStats['security']['overload_drops'] += $generalStats['overload_drops'] ?? 0;
                        $aggregatedStats['security']['timedout_packets'] += $generalStats['timedout_packets'] ?? 0;
                        $aggregatedStats['security']['corrupt_packets'] += $generalStats['corrupt_packets'] ?? 0;
                        $aggregatedStats['security']['unauth_packets'] += $generalStats['unauth_packets'] ?? 0;
                        $aggregatedStats['security']['recursive_queries'] += $generalStats['recursive_queries'] ?? 0;
                    }

                    Log::info("Statistics collected from nameserver {$nameserver->name} for zone {$dnsZone->domain}");
                } else {
                    Log::info("Zone {$dnsZone->domain} does not exist on nameserver {$nameserver->name}, skipping");
                }
            } catch (\Exception $e) {
                Log::warning("Failed to collect statistics from nameserver {$nameserver->name}: " . $e->getMessage());
                $errors++;
            }
        }

        // Salvează statisticile agregate dacă avem date
        if ($statisticsCreated > 0 && $aggregatedStats['total_queries'] > 0) {
            $this->saveAggregatedStatistics($dnsZone, $date, $aggregatedStats);
            Log::info("✅ Aggregated statistics saved for {$dnsZone->domain}", [
                'total_queries' => $aggregatedStats['total_queries'],
                'nameservers' => count($aggregatedStats['nameservers_data']),
                'subdomains' => count($aggregatedStats['subdomains'])
            ]);

            // ✨ Verifică anomalii după colectare
            try {
                $anomalyService = new DnsAnomalyDetectionService();
                $anomalies = $anomalyService->checkAnomalies($dnsZone);
                if (!empty($anomalies)) {
                    Log::warning("Anomalies detected for {$dnsZone->domain}: " . count($anomalies));
                }
            } catch (\Exception $e) {
                Log::warning("Failed to check anomalies: " . $e->getMessage());
            }
        }

        return [
            'statistics_created' => $statisticsCreated,
            'errors' => $errors,
            'nameservers_checked' => $nameservers->count(),
            'total_queries' => $aggregatedStats['total_queries'] ?? 0
        ];
    }

    private function collectFromNameserver(Nameserver $nameserver, $domain, $date)
    {
        $apiUrl = "http://{$nameserver->ip_address}:{$nameserver->api_port}/api/v1";

        Log::debug("Collecting from nameserver: {$nameserver->name}");

        // Verifică dacă zona există pe acest nameserver
        if (!$this->zoneExistsOnNameserver($apiUrl, $nameserver->api_key, $domain)) {
            Log::warning("Zone {$domain} does not exist on {$nameserver->name}, skipping");
            return null;
        }

        // Colectează statisticile generale
        $generalStats = $this->getGeneralStatistics($apiUrl, $nameserver->api_key);

        if (!$generalStats) {
            Log::warning("Failed to get general statistics from {$nameserver->name}");
            return null;
        }

        // Colectează statisticile specifice pentru zona (din log-uri dacă sunt disponibile)
        $zoneStats = $this->getZoneSpecificStatistics($apiUrl, $nameserver->api_key, $domain, $nameserver, $date);

        // Returnează datele pentru agregare (nu mai salvăm individual)
        return [
            'general' => $generalStats,
            'zone_specific' => $zoneStats,
            'nameserver' => $nameserver->name
        ];
    }

    private function zoneExistsOnNameserver($apiUrl, $apiKey, $domain)
    {
        try {
            // PowerDNS necesită zona cu punct la final (FQDN format)
            $zoneId = rtrim($domain, '.') . '.';

            Log::debug("Checking zone existence: {$zoneId} on {$apiUrl}");

            $response = Http::withHeaders([
                'X-API-Key' => $apiKey
            ])->get("{$apiUrl}/servers/localhost/zones/{$zoneId}");

            $exists = $response->successful();
            Log::debug("Zone {$zoneId} exists: " . ($exists ? 'YES' : 'NO') . ", Status: {$response->status()}");

            return $exists;
        } catch (\Exception $e) {
            Log::warning("Exception checking zone existence: " . $e->getMessage());
            return false;
        }
    }

    private function getGeneralStatistics($apiUrl, $apiKey)
    {
        try {
            $response = Http::withHeaders([
                'X-API-Key' => $apiKey
            ])->timeout(30)->get("{$apiUrl}/servers/localhost/statistics");

            if ($response->successful()) {
                $body = $response->body();

                // Verifică dacă body-ul este prea mare
                if (strlen($body) > 5000000) { // 5MB
                    Log::warning("Statistics response too large: " . strlen($body) . " bytes");
                    return null;
                }

                // Curăță caractere UTF-8 invalide
                $body = mb_convert_encoding($body, 'UTF-8', 'UTF-8');

                $data = json_decode($body, true, 512, JSON_BIGINT_AS_STRING);

                if (json_last_error() !== JSON_ERROR_NONE) {
                    Log::error("JSON decode error: " . json_last_error_msg() . ", Body length: " . strlen($body));
                    return null;
                }

                if (!is_array($data)) {
                    Log::error("Statistics data is not an array");
                    return null;
                }

                return $this->parseStatistics($data);
            }
        } catch (\Exception $e) {
            Log::warning("Failed to get general statistics: " . $e->getMessage());
        }

        return null;
    }

    private function getZoneSpecificStatistics($apiUrl, $apiKey, $domain, $nameserver = null, $date = null)
    {
        // Încearcă să obțină statistici din log-urile PowerDNS
        if ($nameserver) {
            try {
                // Folosește web_port dacă este setat, altfel fallback la 8082
                $webPort = $nameserver->web_port ?? 8082;

                // Apelează endpoint custom PHP pentru a citi log-urile
                $queryLogsUrl = "http://{$nameserver->ip_address}:{$webPort}/query-logs.php";

                Log::debug("Attempting to fetch query logs from: {$queryLogsUrl}");

                $response = Http::withHeaders([
                    'X-API-Key' => $apiKey
                ])->timeout(30)->get($queryLogsUrl, [
                    'q' => $domain,
                    'max' => 1000  // Redus la 1000 pentru a evita query-uri exagerate
                ]);

                if ($response->successful()) {
                    $data = $response->json();

                    // Verifică dacă răspunsul este valid
                    if (isset($data['success']) && $data['success'] === true && isset($data['logs'])) {
                        Log::info("✅ Retrieved {$data['lines_returned']} log lines for {$domain} from {$nameserver->name}");

                        // Parsează log-urile pentru acest domeniu cu filtrare pe dată
                        return $this->parseQueryLogs($data['logs'], $domain, $date);
                    } else {
                        Log::warning("Invalid response from query-logs.php on {$nameserver->name}");
                    }
                } else {
                    Log::debug("Query logs endpoint returned {$response->status()} on {$nameserver->name}");
                }
            } catch (\Exception $e) {
                Log::debug("Could not get query logs from {$nameserver->name}: " . $e->getMessage());
            }
        }

        // Fallback: returnează null pentru a folosi estimarea
        return null;
    }

    private function parseQueryLogs($logs, $domain, $targetDate = null)
    {
        if (!is_array($logs) || empty($logs)) {
            return null;
        }

        // Dacă nu este specificată o dată țintă, folosește data curentă
        if (!$targetDate) {
            $targetDate = Carbon::now()->format('Y-m-d');
        }

        $stats = [
            'total_queries' => 0,
            'cache_hits' => 0,
            'cache_misses' => 0,
            'query_types' => [],
            'client_ips' => [],
            'hourly_queries' => array_fill(0, 24, 0), // 0-23 ore
            'subdomains' => [], // Distribuție pe subdomenii
            'protocols' => ['udp' => 0, 'tcp' => 0, 'ipv4' => 0, 'ipv6' => 0]
        ];

        $normalizedDomain = rtrim($domain, '.');
        $totalLogLines = count($logs);
        $matchedLines = 0;
        $skippedDifferentDate = 0;

        // Log primul enÎncearcă pentru debugging
        if (!empty($logs)) {
            Log::debug("Parsing {$totalLogLines} log lines for domain: {$normalizedDomain}");
            Log::debug("Sample log entry: " . substr($logs[0], 0, 200));
        }

        foreach ($logs as $logEntry) {
            if (!is_string($logEntry)) {
                continue;
            }

            // Extrage timestamp - mai multe formate posibile
            $hour = null;
            $timestamp = null;
            $logDate = null;

            // Format 1: "Nov 11 12:45:23"
            if (preg_match('/([A-Z][a-z]{2})\s+(\d{1,2})\s+(\d{2}):(\d{2}):(\d{2})/', $logEntry, $timeMatches)) {
                try {
                    $month = $timeMatches[1];
                    $day = (int)$timeMatches[2];
                    $time = $timeMatches[3] . ':' . $timeMatches[4] . ':' . $timeMatches[5];
                    $year = date('Y'); // Anul curent

                    // Creează un Carbon object în UTC
                    $timestampUTC = Carbon::createFromFormat('Y M d H:i:s', "{$year} {$month} {$day} {$time}", 'UTC');

                    // Extrage data în UTC pentru filtrare
                    $logDate = $timestampUTC->format('Y-m-d');

                    // Convertește la timezone-ul aplicației pentru ora locală
                    $timestamp = $timestampUTC->copy()->setTimezone(config('app.timezone'));
                    $hour = (int)$timestamp->format('H');
                } catch (\Exception $e) {
                    Log::debug("Failed to parse timestamp: " . $e->getMessage());
                }
            }
            // Format 2: "2025-11-11 12:45:23" (ISO format)
            elseif (preg_match('/(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})/', $logEntry, $timeMatches)) {
                try {
                    $timestampUTC = Carbon::createFromFormat('Y-m-d H:i:s',
                        "{$timeMatches[1]}-{$timeMatches[2]}-{$timeMatches[3]} {$timeMatches[4]}:{$timeMatches[5]}:{$timeMatches[6]}",
                        'UTC'
                    );

                    // Extrage data în UTC pentru filtrare
                    $logDate = $timestampUTC->format('Y-m-d');

                    // Convertește la timezone-ul aplicației pentru ora locală
                    $timestamp = $timestampUTC->copy()->setTimezone(config('app.timezone'));
                    $hour = (int)$timestamp->format('H');
                } catch (\Exception $e) {
                    Log::debug("Failed to parse ISO timestamp: " . $e->getMessage());
                }
            }
            // Format 3: Doar ora "12:45:23" (fără dată - presupunem data țintă)
            elseif (preg_match('/(\d{2}):(\d{2}):(\d{2})/', $logEntry, $timeMatches)) {
                try {
                    // Folosim data țintă cu ora din log în UTC
                    $timestampUTC = Carbon::createFromFormat('Y-m-d H:i:s',
                        $targetDate . ' ' . $timeMatches[1] . ':' . $timeMatches[2] . ':' . $timeMatches[3],
                        'UTC'
                    );

                    // date este deja targetDate
                    $logDate = $targetDate;

                    // Convertește la timezone-ul aplicației pentru ora locală
                    $timestamp = $timestampUTC->copy()->setTimezone(config('app.timezone'));
                    $hour = (int)$timestamp->format('H');
                } catch (\Exception $e) {
                    Log::debug("Failed to parse time-only timestamp: " . $e->getMessage());
                }
            }

            // Filtrare pe dată: Compară datele în UTC pentru a evita problemele de timezone
            if ($logDate && $logDate !== $targetDate) {
                $skippedDifferentDate++;
                continue;
            }

            // Format: "Remote 172.69.21.201 wants 'itdatetelecom.ro|A', do=1: packetcache HIT"
            if (preg_match('/Remote\s+([0-9.:a-fA-F]+)\s+wants\s+\'([^|]+)\|([A-Z0-9]+)\'.*?(packetcache|query-cache)\s+(HIT|MISS)/i', $logEntry, $matches)) {
                $ip = $matches[1];
                $queriedDomain = rtrim($matches[2], '.');
                $queryType = $matches[3];
                $cacheResult = strtoupper($matches[5]); // HIT sau MISS

                // Detectează protocol
                $isIPv6 = strpos($ip, ':') !== false && substr_count($ip, ':') > 1;

                // Verifică dacă query-ul este pentru domeniul nostru sau subdomeniile sale
                if ($queriedDomain === $normalizedDomain ||
                    str_ends_with($queriedDomain, '.' . $normalizedDomain)) {

                    $matchedLines++;
                    $stats['total_queries']++;

                    if ($cacheResult === 'HIT') {
                        $stats['cache_hits']++;
                    } else {
                        $stats['cache_misses']++;
                    }

                    // Contorizează tipurile de query
                    if (!isset($stats['query_types'][$queryType])) {
                        $stats['query_types'][$queryType] = 0;
                    }
                    $stats['query_types'][$queryType]++;

                    // Contorizează IP-urile client
                    if (!isset($stats['client_ips'][$ip])) {
                        $stats['client_ips'][$ip] = 0;
                    }
                    $stats['client_ips'][$ip]++;

                    // ✨ NOU: Distribuție orară
                    if ($hour !== null && $hour >= 0 && $hour < 24) {
                        $stats['hourly_queries'][$hour]++;
                    }

                    // ✨ NOU: Top subdomenii
                    if (!isset($stats['subdomains'][$queriedDomain])) {
                        $stats['subdomains'][$queriedDomain] = 0;
                    }
                    $stats['subdomains'][$queriedDomain]++;

                    // ✨ NOU: Protocol distribution
                    if ($isIPv6) {
                        $stats['protocols']['ipv6']++;
                    } else {
                        $stats['protocols']['ipv4']++;
                    }
                    // UDP este default, TCP ar trebui detectat din log (dacă există indicator)
                    $stats['protocols']['udp']++;
                }
            }
        }

        // Log statistici colectate
        Log::info("Parsed query logs for {$domain} on {$targetDate}", [
            'target_date' => $targetDate,
            'total_log_lines' => $totalLogLines,
            'matched_lines' => $matchedLines,
            'skipped_different_date' => $skippedDifferentDate,
            'total_queries' => $stats['total_queries'],
            'filter_ratio' => $totalLogLines > 0 ? round(($matchedLines / $totalLogLines) * 100, 2) . '%' : '0%',
            'hourly_queries_sum' => array_sum($stats['hourly_queries']),
            'subdomains_count' => count($stats['subdomains']),
            'sample_subdomains' => array_slice($stats['subdomains'], 0, 3, true)
        ]);

        return $stats;
    }

    private function parseStatistics($rawStats)
    {
        if (!is_array($rawStats)) {
            return null;
        }

        $parsed = [
            'total_queries' => 0,
            'cache_hits' => 0,
            'cache_misses' => 0,
            'servfail_responses' => 0,
            'nxdomain_responses' => 0,
            'noerror_responses' => 0,
            'latency' => 0,
            'tcp_queries' => 0,
            'udp_queries' => 0,
            'query_types' => [],
            'client_ips' => []
        ];

        foreach ($rawStats as $stat) {
            $name = $stat['name'] ?? '';
            // Skip array values (ring buffers)
            if (is_array($stat['value'] ?? null)) {
                continue;
            }
            $value = (int)($stat['value'] ?? 0);

            // Mapează statisticile PowerDNS (verifică toate variantele posibile)
            switch (true) {
                case stripos($name, 'packetcache-hit') !== false:
                case stripos($name, 'query-cache-hit') !== false:
                    $parsed['cache_hits'] += $value;
                    break;
                case stripos($name, 'packetcache-miss') !== false:
                case stripos($name, 'query-cache-miss') !== false:
                    $parsed['cache_misses'] += $value;
                    break;
                case $name === 'udp-queries':
                    $parsed['udp_queries'] = $value;
                    $parsed['total_queries'] += $value;
                    break;
                case $name === 'tcp-queries':
                    $parsed['tcp_queries'] = $value;
                    $parsed['total_queries'] += $value;
                    break;
                case stripos($name, 'servfail-answers') !== false:
                case stripos($name, 'servfail-packets') !== false:
                    $parsed['servfail_responses'] += $value;
                    break;
                case stripos($name, 'nxdomain-answers') !== false:
                case stripos($name, 'nxdomain-packets') !== false:
                    $parsed['nxdomain_responses'] += $value;
                    break;
                case stripos($name, 'noerror-answers') !== false:
                case stripos($name, 'noerror-packets') !== false:
                    $parsed['noerror_responses'] += $value;
                    break;
                case $name === 'latency':
                    $parsed['latency'] = $value; // microseconds
                    break;
                // ✨ DNSSEC Statistics
                case $name === 'signatures':
                    $parsed['dnssec_signatures'] = $value;
                    break;
                case $name === 'udp-do-queries':
                    $parsed['dnssec_do_queries'] = $value;
                    break;
                case stripos($name, 'dnskey') !== false:
                    if (!isset($parsed['dnssec_dnskey_queries'])) {
                        $parsed['dnssec_dnskey_queries'] = 0;
                    }
                    $parsed['dnssec_dnskey_queries'] += $value;
                    break;
                // ✨ Rate Limiting / Security Statistics
                case $name === 'overload-drops':
                    $parsed['overload_drops'] = $value;
                    break;
                case $name === 'timedout-packets':
                    $parsed['timedout_packets'] = $value;
                    break;
                case $name === 'corrupt-packets':
                    $parsed['corrupt_packets'] = $value;
                    break;
                case $name === 'unauth-packets':
                    $parsed['unauth_packets'] = $value;
                    break;
                case $name === 'security-status':
                    $parsed['security_status'] = $value;
                    break;
                case $name === 'rd-queries':
                    $parsed['recursive_queries'] = $value;
                    break;
            }
        }

        // Dacă total_queries nu a fost setat, calculează din cache hits + misses
        if ($parsed['total_queries'] == 0) {
            $parsed['total_queries'] = $parsed['cache_hits'] + $parsed['cache_misses'];
        }

        $parsed['cache_hit_ratio'] = $parsed['total_queries'] > 0
            ? round(($parsed['cache_hits'] / $parsed['total_queries']) * 100, 2)
            : 0;

        return $parsed;
    }

    private function parseQueryLog($logEntry, &$parsed)
    {
        // Exemplu: "Remote 172.69.21.201 wants 'webdisk.cy.vision|A', do = 1, bufsize = 1232 (1452): packetcache HIT"
        if (preg_match('/Remote\s+([0-9.]+)\s+wants\s+\'[^|]+\|([A-Z]+)\'/', $logEntry, $matches)) {
            $ip = $matches[1];
            $queryType = $matches[2];

            // Contorizează tipurile de query
            if (!isset($parsed['query_types'][$queryType])) {
                $parsed['query_types'][$queryType] = 0;
            }
            $parsed['query_types'][$queryType]++;

            // Contorizează IP-urile client
            if (!isset($parsed['client_ips'][$ip])) {
                $parsed['client_ips'][$ip] = 0;
            }
            $parsed['client_ips'][$ip]++;
        }
    }

    private function processAndSaveStatistics(Nameserver $nameserver, $domain, $date, $generalStats, $zoneStats)
    {
        if (!$generalStats) {
            return null;
        }

        $carbonDate = Carbon::parse($date);

        $queryTypes = [];
        $clientIps = [];
        $totalQueriesForDomain = 0;
        $cacheHitsForDomain = 0;
        $cacheMissesForDomain = 0;
        $cacheHitRatio = 0;
        $isEstimated = true;

        // Verifică dacă avem statistici REALE din log-uri
        if ($zoneStats && isset($zoneStats['total_queries']) && $zoneStats['total_queries'] > 0) {
            // STATISTICI REALE din log-uri PowerDNS
            $totalQueriesForDomain = $zoneStats['total_queries'];
            $cacheHitsForDomain = $zoneStats['cache_hits'];
            $cacheMissesForDomain = $zoneStats['cache_misses'];
            $cacheHitRatio = $totalQueriesForDomain > 0
                ? round(($cacheHitsForDomain / $totalQueriesForDomain) * 100, 2)
                : 0;
            $queryTypes = $zoneStats['query_types'] ?? [];
            $clientIps = $zoneStats['client_ips'] ?? [];
            $isEstimated = false;

            Log::info("REAL statistics from logs for {$domain}", [
                'total_queries' => $totalQueriesForDomain,
                'cache_hits' => $cacheHitsForDomain,
                'cache_hit_ratio' => $cacheHitRatio,
                'source' => 'query_logs'
            ]);
        } else {
            // FALLBACK: Estimare proporțională (comportament vechi)
            $totalZones = 1;
            if ($generalStats && isset($generalStats['total_queries']) && $generalStats['total_queries'] > 0) {
                try {
                    $zonesResponse = Http::withHeaders([
                        'X-API-Key' => $nameserver->api_key
                    ])->get("http://{$nameserver->ip_address}:{$nameserver->api_port}/api/v1/servers/localhost/zones");

                    if ($zonesResponse->successful()) {
                        $zones = $zonesResponse->json();
                        $totalZones = is_array($zones) ? count($zones) : 1;
                    }
                } catch (\Exception $e) {
                    Log::warning("Could not get total zones count: " . $e->getMessage());
                }

                $totalQueriesForDomain = (int)($generalStats['total_queries'] / max($totalZones, 1));
                $cacheHitsForDomain = (int)($generalStats['cache_hits'] / max($totalZones, 1));
                $cacheMissesForDomain = (int)($generalStats['cache_misses'] / max($totalZones, 1));
                $cacheHitRatio = $generalStats['cache_hit_ratio'] ?? 0;

                Log::info("ESTIMATED statistics for {$domain}", [
                    'total_zones' => $totalZones,
                    'estimated_queries' => $totalQueriesForDomain,
                    'cache_hit_ratio' => $cacheHitRatio,
                    'source' => 'estimation'
                ]);
            }
        }

        // Sortează descrescător după numărul de query-uri
        arsort($queryTypes);
        arsort($clientIps);

        // Verifică dacă statisticile pentru această dată există deja
        $existingStat = DnsZoneStatistic::where([
            'domain' => $domain,
            'nameserver_id' => $nameserver->id,
            'statistic_date' => $carbonDate,
            'period_type' => 'daily'
        ])->first();

        $rawStatistics = [
            'general' => $generalStats,
            'zone_specific' => $zoneStats,
            'collected_at' => now()->toISOString()
        ];

        // ✨ Procesează statistici noi
        $hourlyQueries = $zoneStats['hourly_queries'] ?? null;
        $subdomains = $zoneStats['subdomains'] ?? [];
        $protocols = $zoneStats['protocols'] ?? null;

        // Top 10 subdomenii
        if (!empty($subdomains)) {
            arsort($subdomains);
            $topSubdomains = array_slice($subdomains, 0, 10, true);
        } else {
            $topSubdomains = null;
        }

        // Statistici geografice (DEZACTIVAT temporar pentru performanță)
        // TODO: Rulează în background cu queue job
        $geographicDistribution = null;
        // if (!empty($clientIps)) {
        //     $geographicDistribution = $this->getGeographicDistribution($clientIps);
        // }

        // Statistici comparative (compară cu ziua anterioară)
        $comparisonStats = $this->getComparisonStats($domain, $nameserver->id, $carbonDate, $totalQueriesForDomain);

        $data = [
            'domain' => $domain,
            'nameserver_id' => $nameserver->id,
            'statistic_date' => $carbonDate,
            'period_type' => 'daily',
            'raw_statistics' => $rawStatistics,
            'total_queries' => $totalQueriesForDomain, // Folosește query-urile DOAR pentru acest domeniu
            'cache_hits' => $cacheHitsForDomain,
            'cache_misses' => $cacheMissesForDomain,
            'servfail_responses' => 0, // TODO: Parsează din log-uri dacă este necesar
            'nxdomain_responses' => 0, // TODO: Parsează din log-uri dacă este necesar
            'noerror_responses' => $totalQueriesForDomain, // Aproximare
            'cache_hit_ratio' => $cacheHitRatio,
            'top_query_types' => !empty($queryTypes) ? array_slice($queryTypes, 0, 10, true) : null,
            'top_client_ips' => !empty($clientIps) ? array_slice($clientIps, 0, 20, true) : null,
            'hourly_queries' => $hourlyQueries, // ✨ NOU
            'top_subdomains' => $topSubdomains, // ✨ NOU
            'geographic_distribution' => $geographicDistribution, // ✨ NOU
            'comparison_stats' => $comparisonStats, // ✨ NOU
            'protocol_distribution' => $protocols, // ✨ NOU
            'collected_at' => now()
        ];

        if ($existingStat) {
            $existingStat->update($data);
            return $existingStat;
        } else {
            return DnsZoneStatistic::create($data);
        }
    }

    /**
     * Salvează statisticile agregate de pe toate nameserverele
     */
    private function saveAggregatedStatistics($dnsZone, $date, $aggregatedStats)
    {
        $carbonDate = Carbon::parse($date);

        // Calculează cache hit ratio
        $cacheHitRatio = $aggregatedStats['total_queries'] > 0
            ? round(($aggregatedStats['cache_hits'] / $aggregatedStats['total_queries']) * 100, 2)
            : 0;

        // Sortează subdomenii și ia top 10
        arsort($aggregatedStats['subdomains']);
        $topSubdomains = array_slice($aggregatedStats['subdomains'], 0, 10, true);

        // Sortează query types și ia top 10
        arsort($aggregatedStats['query_types']);
        $topQueryTypes = array_slice($aggregatedStats['query_types'], 0, 10, true);

        // Sortează client IPs și ia top 20
        arsort($aggregatedStats['client_ips']);
        $topClientIps = array_slice($aggregatedStats['client_ips'], 0, 20, true);

        // Statistici comparative (folosește NULL pentru statistici agregate)
        $comparisonStats = $this->getComparisonStats($dnsZone->domain, null, $carbonDate, $aggregatedStats['total_queries']);

        // Șterge înregistrările vechi pentru această dată (de pe nameservere individuale)
        DnsZoneStatistic::where('domain', $dnsZone->domain)
            ->where('statistic_date', $carbonDate)
            ->where('period_type', 'daily')
            ->whereNotNull('nameserver_id') // Șterge doar cele individuale, nu agregatul
            ->delete();

        // Asigură-te că hourly_queries are întotdeauna 24 de elemente
        $hourlyQueries = $aggregatedStats['hourly_queries'];
        if (!is_array($hourlyQueries) || count($hourlyQueries) !== 24) {
            $hourlyQueries = array_fill(0, 24, 0);
            // Copiază datele existente dacă sunt disponibile
            if (is_array($aggregatedStats['hourly_queries'])) {
                foreach ($aggregatedStats['hourly_queries'] as $hour => $count) {
                    if ($hour >= 0 && $hour < 24) {
                        $hourlyQueries[$hour] = $count;
                    }
                }
            }
        }

        // ✨ Calculează SERVFAIL și NXDOMAIN proporțional cu query-urile zonei
        $servfailResponses = 0;
        $nxdomainResponses = 0;
        $avgLatency = 0;

        if ($aggregatedStats['global_total_queries'] > 0 && $aggregatedStats['total_queries'] > 0) {
            // Proporția query-urilor acestei zone din totalul global
            $zoneRatio = $aggregatedStats['total_queries'] / $aggregatedStats['global_total_queries'];

            // Estimează SERVFAIL și NXDOMAIN proporțional
            $servfailResponses = (int)round($aggregatedStats['global_servfail'] * $zoneRatio);
            $nxdomainResponses = (int)round($aggregatedStats['global_nxdomain'] * $zoneRatio);
        }

        // Calculează media latency (în microsecunde)
        if ($aggregatedStats['latency_samples'] > 0) {
            $avgLatency = (int)round($aggregatedStats['avg_latency'] / $aggregatedStats['latency_samples']);
        }

        // NOERROR = total queries - servfail - nxdomain
        $noerrorResponses = max(0, $aggregatedStats['total_queries'] - $servfailResponses - $nxdomainResponses);

        // Salvează sau actualizează înregistrarea agregată (folosind updateOrCreate pentru a evita duplicate)
        DnsZoneStatistic::updateOrCreate(
            [
                'domain' => $dnsZone->domain,
                'nameserver_id' => null, // NULL = agregat de pe toate nameserverele
                'statistic_date' => $carbonDate,
                'period_type' => 'daily'
            ],
            [
                'raw_statistics' => [
                    'aggregated' => true,
                    'nameservers_count' => count($aggregatedStats['nameservers_data']),
                    'collected_at' => now()->format('Y-m-d H:i:s'),
                    'global_stats' => [
                        'total_queries' => $aggregatedStats['global_total_queries'],
                        'servfail' => $aggregatedStats['global_servfail'],
                        'nxdomain' => $aggregatedStats['global_nxdomain'],
                        'avg_latency_us' => $avgLatency
                    ]
                ],
                'total_queries' => $aggregatedStats['total_queries'],
                'cache_hits' => $aggregatedStats['cache_hits'],
                'cache_misses' => $aggregatedStats['cache_misses'],
                'servfail_responses' => $servfailResponses,
                'nxdomain_responses' => $nxdomainResponses,
                'noerror_responses' => $noerrorResponses,
                'cache_hit_ratio' => $cacheHitRatio,
                'top_query_types' => !empty($topQueryTypes) ? $topQueryTypes : null,
                'top_client_ips' => !empty($topClientIps) ? $topClientIps : null,
                'hourly_queries' => $hourlyQueries, // Array cu exact 24 de elemente
                'top_subdomains' => !empty($topSubdomains) ? $topSubdomains : null,
                'geographic_distribution' => null, // Va fi completat de job
                'comparison_stats' => $comparisonStats,
                'protocol_distribution' => $aggregatedStats['protocols'],
                'response_time_avg' => $avgLatency, // ✨ NOU: Latency mediu în microsecunde
                'dnssec_stats' => $aggregatedStats['dnssec'], // ✨ NOU: Statistici DNSSEC
                'security_stats' => $aggregatedStats['security'], // ✨ NOU: Security/Rate limiting
                'collected_at' => now()
            ]
        );

        // ✨ Dispatch job pentru procesare geografică în background
        if (!empty($topClientIps)) {
            try {
                // Găsește statistica salvată pentru a obține ID-ul
                $savedStat = DnsZoneStatistic::where('domain', $dnsZone->domain)
                    ->whereNull('nameserver_id')
                    ->where('statistic_date', $carbonDate)
                    ->where('period_type', 'daily')
                    ->first();

                if ($savedStat) {
                    ProcessGeographicDistributionJob::dispatch($savedStat->id, $topClientIps)
                        ->delay(now()->addSeconds(5)); // Delay mic pentru a nu supraîncărca

                    Log::info("Dispatched geographic distribution job for {$dnsZone->domain}");
                }
            } catch (\Exception $e) {
                Log::warning("Failed to dispatch geographic distribution job: " . $e->getMessage());
            }
        }
    }

    /**
     * Obține distribuția geografică a IP-urilor client
     */
    private function getGeographicDistribution($clientIps)
    {
        try {
            $countries = [];
            $totalIps = 0;

            // Limitează la top 50 IP-uri pentru a nu face prea multe request-uri
            $topIps = array_slice($clientIps, 0, 50, true);

            foreach ($topIps as $ip => $count) {
                try {
                    // Folosește ip-api.com (gratuit, 45 requests/minut)
                    $response = Http::timeout(2)->get("http://ip-api.com/json/{$ip}?fields=status,country,countryCode");

                    if ($response->successful()) {
                        $data = $response->json();
                        if (isset($data['status']) && $data['status'] === 'success') {
                            $countryCode = $data['countryCode'] ?? 'Unknown';
                            $countryName = $data['country'] ?? 'Unknown';

                            if (!isset($countries[$countryCode])) {
                                $countries[$countryCode] = [
                                    'name' => $countryName,
                                    'queries' => 0
                                ];
                            }
                            $countries[$countryCode]['queries'] += $count;
                            $totalIps += $count;
                        }
                    }

                    // Rate limiting: 45 requests/minut = ~1.3 secunde între requests
                    usleep(1400000); // 1.4 secunde
                } catch (\Exception $e) {
                    Log::debug("Could not get geo data for IP {$ip}: " . $e->getMessage());
                }
            }

            // Sortează după număr de queries
            uasort($countries, function($a, $b) {
                return $b['queries'] - $a['queries'];
            });

            return [
                'countries' => $countries,
                'total_queries' => $totalIps,
                'collected_at' => now()->toISOString()
            ];
        } catch (\Exception $e) {
            Log::warning("Failed to get geographic distribution: " . $e->getMessage());
            return null;
        }
    }

    /**
     * Obține statistici comparative cu ultima zi disponibilă (nu neapărat ziua anterioară exactă)
     * Caută în ultimele 7 zile pentru a găsi date de comparație
     */
    private function getComparisonStats($domain, $nameserverId, $currentDate, $currentQueries)
    {
        try {
            $currentDateCarbon = Carbon::parse($currentDate);

            // Construiește query-ul pentru a găsi statisticile anterioare
            // Caută în ultimele 7 zile, excluzând ziua curentă
            $query = DnsZoneStatistic::where('domain', $domain)
                ->where('statistic_date', '<', $currentDateCarbon->format('Y-m-d'))
                ->where('statistic_date', '>=', $currentDateCarbon->copy()->subDays(7)->format('Y-m-d'))
                ->where('period_type', 'daily');

            // Dacă nameserverId este NULL, caută înregistrări agregate (nameserver_id NULL)
            // Altfel, caută pentru nameserver-ul specific
            if ($nameserverId === null) {
                $query->whereNull('nameserver_id');
            } else {
                $query->where('nameserver_id', $nameserverId);
            }

            // Ia cea mai recentă statistică disponibilă
            $previousStat = $query->orderBy('statistic_date', 'desc')->first();

            if (!$previousStat) {
                // Dacă nu există în ultimele 7 zile, încearcă să găsești orice statistică anterioară
                $query = DnsZoneStatistic::where('domain', $domain)
                    ->where('statistic_date', '<', $currentDateCarbon->format('Y-m-d'))
                    ->where('period_type', 'daily');

                if ($nameserverId === null) {
                    $query->whereNull('nameserver_id');
                } else {
                    $query->where('nameserver_id', $nameserverId);
                }

                $previousStat = $query->orderBy('statistic_date', 'desc')->first();

                if (!$previousStat) {
                    return null;
                }
            }

            $previousQueries = $previousStat->total_queries;
            $difference = $currentQueries - $previousQueries;
            $percentageChange = $previousQueries > 0
                ? round(($difference / $previousQueries) * 100, 2)
                : 0;

            // Calculează numărul de zile între cele două statistici (valoare absolută)
            $daysDifference = abs($currentDateCarbon->diffInDays(Carbon::parse($previousStat->statistic_date)));

            return [
                'previous_date' => Carbon::parse($previousStat->statistic_date)->format('Y-m-d'),
                'previous_queries' => $previousQueries,
                'current_queries' => $currentQueries,
                'difference' => $difference,
                'percentage_change' => $percentageChange,
                'trend' => $difference > 0 ? 'up' : ($difference < 0 ? 'down' : 'stable'),
                'days_difference' => $daysDifference // Numărul de zile între comparații
            ];
        } catch (\Exception $e) {
            Log::warning("Failed to get comparison stats: " . $e->getMessage());
            return null;
        }
    }

    public function generateWeeklyStatistics($domain, $week = null)
    {
        if (!$week) {
            $week = Carbon::now()->startOfWeek()->format('Y-m-d');
        }

        $startDate = Carbon::parse($week)->startOfWeek();
        $endDate = $startDate->copy()->endOfWeek();

        return $this->aggregateStatistics($domain, $startDate, $endDate, 'weekly');
    }

    public function generateMonthlyStatistics($domain, $month = null)
    {
        if (!$month) {
            $month = Carbon::now()->startOfMonth()->format('Y-m-d');
        }

        $startDate = Carbon::parse($month)->startOfMonth();
        $endDate = $startDate->copy()->endOfMonth();

        return $this->aggregateStatistics($domain, $startDate, $endDate, 'monthly');
    }

    public function generateYearlyStatistics($domain, $year = null)
    {
        if (!$year) {
            $year = Carbon::now()->startOfYear()->format('Y-m-d');
        }

        $startDate = Carbon::parse($year)->startOfYear();
        $endDate = $startDate->copy()->endOfYear();

        return $this->aggregateStatistics($domain, $startDate, $endDate, 'yearly');
    }

    private function aggregateStatistics($domain, $startDate, $endDate, $periodType)
    {
        $dailyStats = DnsZoneStatistic::forDomain($domain)
            ->forPeriod('daily')
            ->forDateRange($startDate, $endDate)
            ->get()
            ->groupBy('nameserver_id');

        $results = [];

        foreach ($dailyStats as $nameserverId => $stats) {
            $nameserver = Nameserver::find($nameserverId);

            $aggregated = [
                'domain' => $domain,
                'nameserver_id' => $nameserverId,
                'statistic_date' => $startDate,
                'period_type' => $periodType,
                'total_queries' => $stats->sum('total_queries'),
                'cache_hits' => $stats->sum('cache_hits'),
                'cache_misses' => $stats->sum('cache_misses'),
                'servfail_responses' => $stats->sum('servfail_responses'),
                'nxdomain_responses' => $stats->sum('nxdomain_responses'),
                'noerror_responses' => $stats->sum('noerror_responses'),
                'cache_hit_ratio' => $stats->avg('cache_hit_ratio'),
                'collected_at' => now()
            ];

            // Agregare top query types și client IPs
            $allQueryTypes = [];
            $allClientIPs = [];

            foreach ($stats as $stat) {
                if ($stat->top_query_types) {
                    foreach ($stat->top_query_types as $type => $count) {
                        $allQueryTypes[$type] = ($allQueryTypes[$type] ?? 0) + $count;
                    }
                }
                if ($stat->top_client_ips) {
                    foreach ($stat->top_client_ips as $ip => $count) {
                        $allClientIPs[$ip] = ($allClientIPs[$ip] ?? 0) + $count;
                    }
                }
            }

            arsort($allQueryTypes);
            arsort($allClientIPs);

            $aggregated['top_query_types'] = array_slice($allQueryTypes, 0, 10, true);
            $aggregated['top_client_ips'] = array_slice($allClientIPs, 0, 20, true);
            $aggregated['raw_statistics'] = [
                'aggregated_from' => $stats->count() . ' daily records',
                'period' => $periodType,
                'start_date' => $startDate->toDateString(),
                'end_date' => $endDate->toDateString()
            ];

            // Salvează sau actualizează
            $existingStat = DnsZoneStatistic::where([
                'domain' => $domain,
                'nameserver_id' => $nameserverId,
                'statistic_date' => $startDate,
                'period_type' => $periodType
            ])->first();

            if ($existingStat) {
                $existingStat->update($aggregated);
                $results[] = $existingStat;
            } else {
                $results[] = DnsZoneStatistic::create($aggregated);
            }
        }

        return $results;
    }

    private function saveStatistics($dnsZone, $nameserver, $stats, $date)
    {
        $carbonDate = Carbon::parse($date);

        // Creează statistici pentru diferite perioade
        $periods = [
            'daily' => $carbonDate->copy(),
            'weekly' => $carbonDate->copy()->startOfWeek(),
            'monthly' => $carbonDate->copy()->startOfMonth(),
            'yearly' => $carbonDate->copy()->startOfYear()
        ];

        foreach ($periods as $periodType => $periodDate) {
            $statData = [
                'domain' => $dnsZone->domain,
                'nameserver_id' => $nameserver->id,
                'statistic_date' => $periodDate->toDateString(),
                'period_type' => $periodType,
                'raw_statistics' => $stats,
                'total_queries' => $stats['total_queries'] ?? 0,
                'cache_hits' => $stats['cache_hits'] ?? 0,
                'cache_misses' => $stats['cache_misses'] ?? 0,
                'servfail_responses' => $stats['servfail_responses'] ?? 0,
                'nxdomain_responses' => $stats['nxdomain_responses'] ?? 0,
                'noerror_responses' => $stats['noerror_responses'] ?? 0,
                'cache_hit_ratio' => $stats['cache_hit_ratio'] ?? 0,
                'top_query_types' => $stats['top_query_types'] ?? [],
                'top_client_ips' => $stats['top_client_ips'] ?? [],
                'hourly_distribution' => $stats['hourly_distribution'] ?? [],
                'collected_at' => now()
            ];

            // Salvează sau actualizează statistica existentă
            DnsZoneStatistic::updateOrCreate(
                [
                    'domain' => $dnsZone->domain,
                    'nameserver_id' => $nameserver->id,
                    'statistic_date' => $periodDate->toDateString(),
                    'period_type' => $periodType
                ],
                $statData
            );
        }
    }
}
