<?php

namespace App\Services;

use App\Support\NormalizedProjectUrl;
use InvalidArgumentException;

final class ProjectUrlNormalizer
{
    public function normalize(string $input): NormalizedProjectUrl
    {
        $input = trim($input);
        if ($input === '') throw new InvalidArgumentException('Web sitesi adresi zorunludur.');
        if (! preg_match('/^[a-z][a-z0-9+.-]*:/i', $input)) $input = 'https://'.$input;
        $parts = parse_url($input);
        $scheme = strtolower((string) ($parts['scheme'] ?? ''));
        if (! in_array($scheme, ['http', 'https'], true)) throw new InvalidArgumentException('Yalnızca http ve https adresleri kabul edilir.');
        if (isset($parts['user']) || isset($parts['pass'])) throw new InvalidArgumentException('Kullanıcı bilgisi içeren adresler kabul edilmez.');
        $host = strtolower(rtrim((string) ($parts['host'] ?? ''), '.'));
        if ($host === '') throw new InvalidArgumentException('Geçerli bir alan adı girin.');
        if (preg_match('/[^\x00-\x7f]/', $host)) {
            if (! function_exists('idn_to_ascii')) throw new InvalidArgumentException('Uluslararası alan adları bu sunucuda desteklenmiyor.');
            $host = idn_to_ascii($host, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46) ?: '';
        }
        if (str_starts_with($host, 'www.')) $host = substr($host, 4);
        if ($host === 'localhost' || str_ends_with($host, '.localhost') || filter_var($host, FILTER_VALIDATE_IP)) {
            throw new InvalidArgumentException('Yerel veya IP adresleri kabul edilmez.');
        }
        if (strlen($host) > 253 || ! str_contains($host, '.')) throw new InvalidArgumentException('Geçerli bir alan adı girin.');
        foreach (explode('.', $host) as $label) {
            if ($label === '' || strlen($label) > 63 || ! preg_match('/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/', $label)) {
                throw new InvalidArgumentException('Geçerli bir alan adı girin.');
            }
        }
        $port = $parts['port'] ?? null;
        if ($port !== null && ($port < 1 || $port > 65535)) throw new InvalidArgumentException('Geçerli bir port girin.');
        $includePort = $port !== null && !(($scheme === 'http' && $port === 80) || ($scheme === 'https' && $port === 443));
        return new NormalizedProjectUrl($host, $scheme.'://'.$host.($includePort ? ':'.$port : ''));
    }
}
