import logging
import os
import socket
import ipaddress
from urllib.parse import urlparse

from . import strtobool
from .errors import Error

logger = logging.getLogger(__name__)


class InvalidURLError(Error):
    pass


def is_url_valid(url: str) -> bool:
    parsed = urlparse(url)
    if parsed.scheme not in ["http", "https"]:
        return False

    # XXX in debug mode, we want to allow requests to localhost to test the federation with local instances
    debug_mode = strtobool(os.getenv("MICROBLOGPUB_DEBUG", "false"))
    if debug_mode:
        return True

    if parsed.hostname in ["localhost"]:
        return False

    try:
        ip_address = socket.getaddrinfo(parsed.hostname, parsed.port or 80)[0][4][0]
    except socket.gaierror:
        logger.exception(f"failed to lookup url {url}")
        return False

    if ipaddress.ip_address(ip_address).is_private:
        logger.info(f"rejecting private URL {url}")
        return False

    return True


def check_url(url: str) -> None:
    if not is_url_valid(url):
        raise InvalidURLError(f'"{url}" is invalid')

    return None
