<?php

namespace App\Repositories\Domain\Read;

use App\enum\DomainType;
use App\enum\ProviderType;
use App\Models\Domain;
use App\Repositories\BaseRepository;
use Illuminate\Database\Eloquent\Collection;

class DomainReadRepository extends BaseRepository
{
    protected function getCacheTag(): string
    {
        return 'domains';
    }

    public function getModel(): string
    {
        return Domain::class;
    }

    public function findActive(): Collection
    {
        $cacheKey = $this->getCacheKey('active');

        return $this->executeQuery(function () {
            $result = $this->query
                ->where('is_active', true)
                ->where(function ($query) {
                    $query->whereNull('starts_at')
                        ->orWhere('starts_at', '<=', now());
                })
                ->where(function ($query) {
                    $query->whereNull('ends_at')
                        ->orWhere('ends_at', '>=', now());
                })
                ->get();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 1800); // 30 minutes
    }

    public function findActiveByType(?DomainType $domainType = null, ?ProviderType $providerType = null): array
    {
        $params = [
            'domain_type' => $domainType?->value,
            'provider_type' => $providerType?->value,
        ];
        $cacheKey = $this->getCacheKey('active_by_type', $params);

        return $this->executeQuery(function () use ($domainType, $providerType) {
            $query = $this->query
                ->where('is_active', true)
                ->where(function ($query) {
                    $query->whereNull('starts_at')
                        ->orWhere('starts_at', '<=', now());
                })
                ->where(function ($query) {
                    $query->whereNull('ends_at')
                        ->orWhere('ends_at', '>=', now());
                });

            if ($domainType) {
                $query->where('domain_type', $domainType->value);
            }

            if ($providerType) {
                $query->where('provider_type', $providerType->value);
            }

            $result = $query->pluck('name')->toArray();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 1800); // 30 minutes
    }

    public function findActiveByProvider(ProviderType $providerType): Collection
    {
        $cacheKey = $this->getCacheKey('active_by_provider', ['provider' => $providerType->value]);

        return $this->executeQuery(function () use ($providerType) {
            $result = $this->query
                ->where('is_active', true)
                ->where('provider_type', $providerType->value)
                ->where(function ($query) {
                    $query->whereNull('starts_at')
                        ->orWhere('starts_at', '<=', now());
                })
                ->where(function ($query) {
                    $query->whereNull('ends_at')
                        ->orWhere('ends_at', '>=', now());
                })
                ->get();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 1800);
    }

    public function findExpiringSoon(int $days = 7): Collection
    {
        $cacheKey = $this->getCacheKey('expiring_soon', ['days' => $days]);

        return $this->executeQuery(function () use ($days) {
            $result = $this->query
                ->where('is_active', true)
                ->whereNotNull('ends_at')
                ->where('ends_at', '<=', now()->addDays($days))
                ->where('ends_at', '>', now())
                ->orderBy('ends_at', 'asc')
                ->get();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 900); // 15 minutes
    }

    public function findInactive(): Collection
    {
        $cacheKey = $this->getCacheKey('inactive');

        return $this->executeQuery(function () {
            $result = $this->query
                ->where('is_active', false)
                ->orWhere(function ($query) {
                    $query->whereNotNull('starts_at')
                        ->where('starts_at', '>', now());
                })
                ->orWhere(function ($query) {
                    $query->whereNotNull('ends_at')
                        ->where('ends_at', '<', now());
                })
                ->get();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 1800);
    }

    public function findRecentlyUsed(int $hours = 24): Collection
    {
        $cacheKey = $this->getCacheKey('recently_used', ['hours' => $hours]);

        return $this->executeQuery(function () use ($hours) {
            $result = $this->query
                ->whereNotNull('last_used_at')
                ->where('last_used_at', '>=', now()->subHours($hours))
                ->orderBy('last_used_at', 'desc')
                ->get();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 900); // 15 minutes
    }

    public function findByName(string $name): ?Domain
    {
        $cacheKey = $this->getCacheKey('find_by_name', ['name' => $name]);

        return $this->executeQuery(function () use ($name) {
            $result = $this->query->where('name', $name)->first();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 3600); // 1 hour
    }

    public function countActive(): int
    {
        $cacheKey = $this->getCacheKey('count_active');

        return $this->executeQuery(function () {
            $result = $this->query
                ->where('is_active', true)
                ->where(function ($query) {
                    $query->whereNull('starts_at')
                        ->orWhere('starts_at', '<=', now());
                })
                ->where(function ($query) {
                    $query->whereNull('ends_at')
                        ->orWhere('ends_at', '>=', now());
                })
                ->count();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 600); // 10 minutes
    }

    public function countByProvider(): array
    {
        $cacheKey = $this->getCacheKey('count_by_provider');

        return $this->executeQuery(function () {
            $result = $this->query
                ->selectRaw('provider_type, COUNT(*) as count')
                ->groupBy('provider_type')
                ->pluck('count', 'provider_type')
                ->toArray();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 1800);
    }

    public function countByType(): array
    {
        $cacheKey = $this->getCacheKey('count_by_type');

        return $this->executeQuery(function () {
            $result = $this->query
                ->selectRaw('domain_type, COUNT(*) as count')
                ->groupBy('domain_type')
                ->pluck('count', 'domain_type')
                ->toArray();
            $this->resetQuery();

            return $result;
        }, $cacheKey, 1800);
    }
}
