<?php
namespace Crawl\Services\Crawler;

class UrlNormalizer
{
    public function normalize(string $url): ?string
    {
        $url = trim($url);
        if ($url === '') {
            return null;
        }

        $parts = parse_url($url);
        if ($parts === false || empty($parts['host'])) {
            return null;
        }

        $scheme = strtolower($parts['scheme'] ?? 'https');
        $host = strtolower($parts['host']);
        $port = isset($parts['port']) ? ':' . (int)$parts['port'] : '';

        $path = $parts['path'] ?? '/';
        $path = preg_replace('#/+#', '/', $path) ?: '/';
        if ($path !== '/' && str_ends_with($path, '/')) {
            $path = rtrim($path, '/');
        }

        $query = isset($parts['query']) ? '?' . $parts['query'] : '';

        return $scheme . '://' . $host . $port . $path . $query;
    }

    public function toAbsolute(string $baseUrl, string $candidate): ?string
    {
        $candidate = trim($candidate);
        if ($candidate === '' || str_starts_with($candidate, 'javascript:') || str_starts_with($candidate, 'mailto:') || str_starts_with($candidate, 'tel:')) {
            return null;
        }

        if (preg_match('#^https?://#i', $candidate)) {
            return $this->normalize($candidate);
        }

        $base = parse_url($baseUrl);
        if (!$base || empty($base['host'])) {
            return null;
        }

        $scheme = $base['scheme'] ?? 'https';
        $host = $base['host'];
        $port = isset($base['port']) ? ':' . $base['port'] : '';

        if (str_starts_with($candidate, '//')) {
            return $this->normalize($scheme . ':' . $candidate);
        }

        if (str_starts_with($candidate, '/')) {
            return $this->normalize($scheme . '://' . $host . $port . $candidate);
        }

        $basePath = $base['path'] ?? '/';
        $baseDir = rtrim(str_replace('\\', '/', dirname($basePath)), '/');
        $baseDir = $baseDir === '' ? '/' : $baseDir . '/';

        return $this->normalize($scheme . '://' . $host . $port . $baseDir . $candidate);
    }

    public function isInternal(string $domain, string $url): bool
    {
        $domainParts = parse_url($domain);
        $urlParts = parse_url($url);

        if (!$domainParts || !$urlParts || empty($domainParts['host']) || empty($urlParts['host'])) {
            return false;
        }

        return strtolower($domainParts['host']) === strtolower($urlParts['host']);
    }
}
