<?php

namespace App\Representation\Service;

use App\Location\Repository\CityRepository;
use App\Representation\Entity\Representation;
use App\Representation\Repository\RepresentationRepository;

/**
 * تنها نقطه‌ی نگاشت host → context در backend. هیچ سرویس/کنترلر دیگری نباید
 * مستقیماً دامنه را parse یا با cities/representations تطبیق دهد.
 *
 * ورودی هر شکلی از آدرس را می‌پذیرد (host خالص، URL کامل، با www/پورت).
 */
class DomainContextResolver
{
    public function __construct(
        private readonly CityRepository           $cityRepo,
        private readonly RepresentationRepository $representationRepo,
    ) {}

    /**
     * اعمال scope دامنه روی فیلترهای لیست‌های عمومی (doctors/clinics):
     * دامنه‌ی نماینده‌ی سراسری → فقط ردیف‌های همان نماینده؛ فیلتر شهر/استان بی‌اثر.
     * دامنه‌ی شهری/ناشناخته → فیلترها دست‌نخورده (فقط کلید domain حذف می‌شود).
     */
    public function applyToListFilters(array $filters): array
    {
        $domain = $filters['domain'] ?? null;
        unset($filters['domain']);
        if (!is_string($domain) || $domain === '') {
            return $filters;
        }

        $ctx = $this->resolve($domain);
        if ($ctx->isGlobalRepresentation) {
            $filters['representation_id'] = $ctx->representationId();
            unset($filters['city_id'], $filters['state_id'], $filters['city'], $filters['state']);
        }

        return $filters;
    }

    public function resolve(?string $hostOrUrl): DomainContext
    {
        $domain = Representation::normalizeDomain($hostOrUrl);
        if ($domain === null) {
            return DomainContext::empty();
        }

        $city = $this->cityRepo->findByDomain($domain);
        if ($city !== null) {
            // دامنه‌ی شهری؛ نماینده‌ای که دامنه‌ی اختصاصی‌اش این باشد وجود ندارد،
            // ولی ممکن است نماینده‌ای دامنه‌ی شهر را به‌عنوان دامنه‌ی خودش ثبت کرده باشد.
            $rep = $this->representationRepo->findActiveByDomain($domain);
            return new DomainContext($rep, $city, false);
        }

        // exact ابتدا (production: host = دامنه‌ی واقعی)، سپس fallback اولین-label
        // (dev: host = `<prefix>.localhost` باید نماینده‌ی `<prefix>.ir` را بیابد).
        $rep = $this->representationRepo->findActiveByDomain($domain)
            ?? $this->representationRepo->findActiveByDomainPrefix(explode('.', $domain)[0]);
        if ($rep !== null) {
            return new DomainContext($rep, null, $rep->isGlobal());
        }

        return DomainContext::empty();
    }
}
