import requests
from urllib.parse import quote as url_quote, urlsplit, urlunsplit

try:
    import xbmcaddon
    import xbmc

    ADDON = xbmcaddon.Addon()

    def get_setting(key):
        return ADDON.getSetting(key)

    def get_addon_name():
        return ADDON.getAddonInfo("name")

    def log(msg, level=xbmc.LOGINFO):
        xbmc.log(f"[FKStream] {_sanitize_log_message(msg)}", level)

except ImportError:
    # Fallback pour les tests hors Kodi
    def get_setting(key):
        return ""

    def get_addon_name():
        return "FKStream"

    def log(msg, level=0):
        print(f"[FKStream] {_sanitize_log_message(msg)}")


def get_base_url():
    url = get_setting("base_url").strip().rstrip("/")
    return url


def get_secret_string():
    return get_setting("secret_string").strip()


def is_configured():
    return bool(get_base_url()) and bool(get_secret_string())


def redact_config_url(url):
    secret = get_secret_string()
    if not secret:
        return url
    return str(url).replace(secret, "***")


def _sanitize_log_message(message):
    return "".join(
        character if character >= " " and character != "\x7f" else "?"
        for character in redact_config_url(str(message))
    )


def _safe_log_url(url):
    try:
        parsed = urlsplit(redact_config_url(url))
        hostname = parsed.hostname
        if not parsed.scheme or not hostname:
            return "<URL invalide>"
        if ":" in hostname:
            hostname = f"[{hostname}]"
        if parsed.port is not None:
            hostname = f"{hostname}:{parsed.port}"
        return urlunsplit((parsed.scheme, hostname, parsed.path, "", ""))
    except (TypeError, ValueError):
        return "<URL invalide>"


def api_get(path, timeout=15):
    base = get_base_url()
    if not base:
        log("Erreur: URL du serveur non configurée")
        return None

    url = f"{base}{path}"
    safe_url = _safe_log_url(url)
    log(f"API GET: {safe_url}")

    try:
        resp = requests.get(url, timeout=timeout)
        resp.raise_for_status()
        return resp.json()
    except requests.exceptions.Timeout:
        log(f"Timeout sur {safe_url}")
        return None
    except requests.exceptions.RequestException as exc:
        log(f"Erreur requête {safe_url}: {type(exc).__name__}")
        return None
    except ValueError:
        log(f"Réponse non-JSON depuis {safe_url}")
        return None


def build_catalog_url(search=None, genre=None, sort=None):
    secret = get_secret_string()
    prefix = f"/{secret}" if secret else ""
    parts = []
    if search:
        parts.append(f"search={url_quote(search, safe='')}")
    if genre:
        parts.append(f"genre={url_quote(genre, safe='')}")
    if sort:
        parts.append(f"sort={url_quote(sort, safe='')}")

    if parts:
        return f"{prefix}/catalog/anime/fankai_catalog/{'&'.join(parts)}.json"
    return f"{prefix}/catalog/anime/fankai_catalog.json"


def build_meta_url(anime_id):
    secret = get_secret_string()
    prefix = f"/{secret}" if secret else ""
    return f"{prefix}/meta/anime/{anime_id}.json"


def build_stream_url(media_id):
    secret = get_secret_string()
    if secret:
        return f"/{secret}/stream/anime/{media_id}.json?kodi=1"
    return f"/stream/anime/{media_id}.json?kodi=1"


def is_elementum_installed():
    try:
        xbmcaddon.Addon("plugin.video.elementum")
        return True
    except Exception:
        return False


def build_magnet_uri(info_hash, trackers=None, display_name=None):
    """
    Construit une URI magnet à partir d'un infoHash et de sources/trackers.
    Les sources au format 'tracker:url' sont converties en paramètres &tr=.
    Les sources 'dht:hash' sont ajoutées en paramètres &dht=.
    """
    parts = [f"magnet:?xt=urn:btih:{info_hash.strip()}"]

    if display_name:
        parts.append(f"dn={url_quote(display_name, safe='')}")

    seen = set()
    if trackers:
        for source in trackers:
            if source.startswith("tracker:"):
                stype, svalue = "tr", source[len("tracker:"):]
            elif source.startswith("dht:"):
                stype, svalue = "dht", source[len("dht:"):]
            else:
                stype, svalue = "tr", source

            svalue = svalue.strip()
            if not svalue:
                continue

            key = (stype, svalue)
            if key in seen:
                continue
            seen.add(key)

            parts.append(f"{stype}={url_quote(svalue, safe='')}")

    return "&".join(parts)
