"""Domain normalization utilities.

This module provides domain extraction and normalization from
URLs, email addresses, and hostnames.
"""

from __future__ import annotations

import logging
from typing import Optional

from ..psl import registrable_root

logger = logging.getLogger(__name__)

# Try to use tldextract for accurate PSL handling
try:
    import tldextract  # type: ignore
    _HAS_TLDEXTRACT = True
except ImportError:
    tldextract = None  # type: ignore
    _HAS_TLDEXTRACT = False


def normalize_domain(s: Optional[str]) -> Optional[str]:
    """Extract registrable domain from email, URL, or hostname.

    This function handles multiple input formats:
    - Email: "user@example.com" → "example.com"
    - Full URL: "https://www.example.co.uk/path" → "example.co.uk"
    - Hostname: "www.example.com" → "example.com"
    - Bare domain: "example.com" → "example.com"

    Correctly handles multi-part TLDs like .co.uk, .com.au, etc.

    Args:
        s: Input string (email, URL, or domain)

    Returns:
        Registrable domain in lowercase, or None if invalid/empty

    Examples:
        >>> normalize_domain("user@company.co.uk")
        "company.co.uk"
        >>> normalize_domain("https://www.example.com/page")
        "example.com"
        >>> normalize_domain("subdomain.example.org")
        "example.org"
    """
    if not s:
        return None

    x = str(s).strip().lower()
    if not x:
        return None

    # Extract domain from email
    if "@" in x:
        x = x.split("@", 1)[1]

    # Strip protocol and www
    x = x.replace("https://", "").replace("http://", "").replace("www.", "")

    # Remove path, query, fragment
    x = x.split("/", 1)[0].split("?", 1)[0].split("#", 1)[0]

    if not x:
        return None

    # Use tldextract if available (most accurate)
    if _HAS_TLDEXTRACT and tldextract:
        try:
            ext = tldextract.extract(x)
            if ext.registered_domain:
                return ext.registered_domain
        except Exception:
            pass

    # Fallback to our PSL-based registrable_root
    result = registrable_root(x)
    if result:
        return result

    # Last resort: keep last two labels
    parts = [p for p in x.split(".") if p]
    if len(parts) >= 2:
        return ".".join(parts[-2:])

    return None


def is_personal_email_domain(domain: str) -> bool:
    """Check if a domain is a personal/freemail domain.

    Args:
        domain: Domain to check (should be normalized first)

    Returns:
        True if the domain is a known personal email provider
    """
    from ..heuristics import FREEMAIL_DOMAINS
    normalized = normalize_domain(domain)
    return normalized in FREEMAIL_DOMAINS if normalized else False


def is_temporary_email_domain(domain: str) -> bool:
    """Check if a domain is a temporary/disposable email domain.

    Args:
        domain: Domain to check (should be normalized first)

    Returns:
        True if the domain is a known disposable email provider
    """
    from ..heuristics import TEMP_DOMAINS
    normalized = normalize_domain(domain)
    return normalized in TEMP_DOMAINS if normalized else False
