<?php

namespace App\Services\Domain;

use App\Models\BlockedDomainPattern;
use Illuminate\Support\Facades\Cache;

/**
 * PRC-133 — checks whether a given domain is on the blocked-pattern
 * brand-protect list. Returns the matching pattern (with reason) or NULL.
 *
 * Active patterns are cached for 5 minutes; the model invalidates on
 * save/delete.
 */
class BlockedDomainChecker
{
    public function check(string $domain): ?BlockedDomainPattern
    {
        $domain = $this->normalize($domain);
        if ($domain === '') {
            return null;
        }

        foreach ($this->patterns() as $pattern) {
            if ($pattern->matches($domain)) {
                return $pattern;
            }
        }

        return null;
    }

    public function isBlocked(string $domain): bool
    {
        return $this->check($domain) !== null;
    }

    /**
     * @return \Illuminate\Support\Collection<int, BlockedDomainPattern>
     */
    private function patterns()
    {
        return Cache::remember(
            BlockedDomainPattern::CACHE_KEY,
            BlockedDomainPattern::CACHE_TTL,
            fn () => BlockedDomainPattern::active()->get(),
        );
    }

    private function normalize(string $domain): string
    {
        $domain = trim(mb_strtolower($domain));
        if ($domain === '') {
            return '';
        }

        // Convert IDN/punycode → ASCII for homoglyph-safe matching
        if (function_exists('idn_to_ascii')) {
            $ascii = @idn_to_ascii($domain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
            if (is_string($ascii) && $ascii !== '') {
                return $ascii;
            }
        }

        return $domain;
    }
}
