<?php

namespace App\Jobs;

use App\Models\DnsZone;
use App\Models\DnsZoneAssignment;
use App\Services\DnsStatisticsService;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

class CollectDnsStatisticsJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $domain;
    protected $date;
    protected $periodTypes;

    /**
     * Create a new job instance.
     */
    public function __construct($domain = null, $date = null, $periodTypes = ['daily'])
    {
        $this->domain = $domain;
        $this->date = $date ?: Carbon::now()->format('Y-m-d');
        $this->periodTypes = $periodTypes;
    }

    /**
     * Execute the job.
     */
    public function handle(DnsStatisticsService $statisticsService): void
    {
        Log::info("Starting DNS statistics collection", [
            'domain' => $this->domain,
            'date' => $this->date,
            'period_types' => $this->periodTypes
        ]);

        try {
            if ($this->domain) {
                // Colectează pentru un domeniu specific
                $this->collectForDomain($statisticsService, $this->domain);
            } else {
                // Colectează pentru toate domeniile
                $this->collectForAllDomains($statisticsService);
            }

            Log::info("DNS statistics collection completed successfully");
        } catch (\Exception $e) {
            Log::error("DNS statistics collection failed", [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            throw $e;
        }
    }

    private function collectForDomain(DnsStatisticsService $statisticsService, $domain)
    {
        foreach ($this->periodTypes as $periodType) {
            switch ($periodType) {
                case 'daily':
                    $statisticsService->collectStatisticsForDomain($domain, $this->date);
                    break;
                case 'weekly':
                    $statisticsService->generateWeeklyStatistics($domain, $this->date);
                    break;
                case 'monthly':
                    $statisticsService->generateMonthlyStatistics($domain, $this->date);
                    break;
                case 'yearly':
                    $statisticsService->generateYearlyStatistics($domain, $this->date);
                    break;
            }
        }

        Log::info("Statistics collected for domain: {$domain}", [
            'period_types' => $this->periodTypes
        ]);
    }

    private function collectForAllDomains(DnsStatisticsService $statisticsService)
    {
        // Obține toate domeniile din baza locală
        $localDomains = DnsZone::pluck('domain')->toArray();

        // Obține domeniile din atribuiri PowerDNS
        $assignedDomains = DnsZoneAssignment::pluck('zone_name')
            ->map(function ($zoneName) {
                return rtrim($zoneName, '.');
            })
            ->toArray();

        // Combină și elimină duplicatele
        $allDomains = array_unique(array_merge($localDomains, $assignedDomains));

        Log::info("Collecting statistics for " . count($allDomains) . " domains", [
            'domains' => $allDomains
        ]);

        foreach ($allDomains as $domain) {
            try {
                $this->collectForDomain($statisticsService, $domain);
            } catch (\Exception $e) {
                Log::warning("Failed to collect statistics for domain: {$domain}", [
                    'error' => $e->getMessage()
                ]);
                // Continuă cu următorul domeniu
            }
        }
    }

    /**
     * Get the tags that should be assigned to the job.
     */
    public function tags(): array
    {
        $tags = ['dns-statistics'];

        if ($this->domain) {
            $tags[] = "domain:{$this->domain}";
        }

        $tags[] = "date:{$this->date}";

        return $tags;
    }
}
