#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
resources/resolvers/thepiratebay.py

Funzioni chiamate dal dispatcher (REGISTRY):
    show_latest()            <- mode=tpb_latest  (ultimi torrent)
    show_search()            <- mode=tpb_search  (cerca)
    show_cats()              <- mode=tpb_cats    (elenco categorie)
    show_cat(cat_id, title)  <- mode=tpb_cat     (torrent di una categoria)

Alias per retrocompatibilità:
    show_top = show_latest   <- mode=tpb_top
"""

import sys
import os
import json
from urllib.parse import quote_plus, quote

_ADDON_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
if _ADDON_ROOT not in sys.path:
    sys.path.insert(0, _ADDON_ROOT)

import variables as var
import functions as func
from models import Item

API_SEARCH = "https://apibay.org/q.php?q={query}&cat={cat}"
API_TOP    = "https://apibay.org/precompiled/data_top100_recent.json"
API_VIDEO  = "https://apibay.org/precompiled/data_top100_video.json"

# Categorie video TPB (solo contenuti video)
# ID ufficiali: https://apibay.org/
CATEGORIES = [
    ('[B][COLOR cyan]Film HD[/COLOR][/B]',            'Film HD'),
    ('[B][COLOR limegreen]Film[/COLOR][/B]',           'Film'),
    ('[B][COLOR yellow]Film 4K / UHD[/COLOR][/B]',    'Film 4K'),
    ('[B][COLOR orange]Serie TV HD[/COLOR][/B]',       'Serie Tv HD'),
    ('[B][COLOR orange]Serie TV[/COLOR][/B]',          'Serie TV'),
    ('[B][COLOR yellow]Serie TV 4K / UHD[/COLOR][/B]','Serie TV 4K'),
    ('[B][COLOR white]Animazione / Clip[/COLOR][/B]',  'Animazione'),
    ('[B][COLOR gray]Sport / Altro Video[/COLOR][/B]', 'Sport/Altro'),
]

# Tracker espliciti — necessari perché Tor non supporta UDP (DHT)
_TRACKERS = [
    "udp://tracker.opentrackr.org:1337/announce",
    "udp://open.tracker.cl:1337/announce",
    "udp://tracker.openbittorrent.com:6969/announce",
    "https://tracker1.520.jp:443/announce",
    "https://opentracker.i2p.rocks:443/announce",
    "https://tracker.tamersunion.org:443/announce",
    "udp://open.demonii.com:1337/announce",
    "udp://tracker.torrent.eu.org:451/announce",
]
_TRACKER_PARAMS = "".join(f"&tr={quote(t)}" for t in _TRACKERS)

# ── Filtro video ──────────────────────────────────────────────────────────────
# Esclude torrent che non sono contenuti video (audio, ebook, software, ecc.)
_NON_VIDEO_EXT = (
    '.mp3', '.flac', '.ogg', '.aac', '.wav', '.opus', '.m4a', '.wma',
    '.epub', '.pdf', '.mobi', '.azw', '.djvu',
    '.zip', '.rar', '.7z', '.tar', '.gz', '.iso',
    '.exe', '.apk', '.dmg', '.deb', '.rpm',
    '.jpg', '.jpeg', '.png', '.gif', '.bmp',
    '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx',
)
_NON_VIDEO_KEYWORDS = (
    'audiobook', 'ebook', 'soundtrack', 'discography', 'album',
    'mp3', 'flac', 'epub', 'pdf', 'software', 'game', 'android',
)

def _is_video(name: str) -> bool:
    nl = name.lower()
    for ext in _NON_VIDEO_EXT:
        if nl.endswith(ext):
            return False
    for kw in _NON_VIDEO_KEYWORDS:
        if kw in nl:
            return False
    return True


# ─────────────────────────────────────────
# FETCH JSON
# ─────────────────────────────────────────

def _fetch_json(url):
    try:
        r = func.get(url)
        if not r or not r.text:
            return []
        return json.loads(r.text)
    except Exception as e:
        func.log(f'[tpb] json errore: {e}')
        return []


# ─────────────────────────────────────────
# BUILD LIST
# ─────────────────────────────────────────

def _build_items(data, limit=40):
    results = []
    seen = set()

    for item in data:
        info_hash = item.get('info_hash')
        name      = item.get('name', 'No title')
        seeds     = int(item.get('seeders', 0))
        size_b    = int(item.get('size', 0))

        if not info_hash:
            continue

        # Filtro: salta tutto ciò che non è video
        if not _is_video(name):
            continue

        magnet = (
            f'magnet:?xt=urn:btih:{info_hash}'
            f'&dn={quote_plus(name)}'
            + _TRACKER_PARAMS
        )

        if magnet in seen:
            continue
        seen.add(magnet)

        elementum_url = 'plugin://plugin.video.elementum/play?uri=' + quote(magnet)

        color = 'limegreen' if seeds > 10 else ('yellow' if seeds > 0 else 'red')

        if size_b >= 1_073_741_824:
            size_str = f'  [COLOR gray]{size_b / 1_073_741_824:.1f} GB[/COLOR]'
        elif size_b >= 1_048_576:
            size_str = f'  [COLOR gray]{size_b / 1_048_576:.0f} MB[/COLOR]'
        else:
            size_str = ''

        results.append({
            'title': f'[B]{name[:70]}[/B] [COLOR {color}]S{seeds}[/COLOR]{size_str}',
            'url'  : elementum_url,
            'type' : 'plugin',
            'thumb': '',
        })

        if len(results) >= limit:
            break

    return results


# ─────────────────────────────────────────
# ULTIMI TORRENT
# ─────────────────────────────────────────

def show_latest():
    """Ultimi torrent video caricati su TPB. mode=tpb_latest"""
    from onion_xml_builder import build_listitem

    var.notify_dialog('The Pirate Bay', 'Carico ultimi torrent...', icon=var.addon_icon)
    data = _fetch_json(API_TOP)
    if not data:
        func.ok_dialog('Errore nel caricamento degli ultimi torrent.')
        return

    items = _build_items(data)
    if not items:
        func.ok_dialog('Nessun torrent video trovato.')
        return
    for entry in items:
        build_listitem(entry)


# Alias retrocompatibilità (mode=tpb_top era già nel dispatcher)
show_top = show_latest


# ─────────────────────────────────────────
# CERCA
# ─────────────────────────────────────────

def show_search():
    """Cerca torrent video su TPB. mode=tpb_search"""
    import xbmc
    from onion_xml_builder import build_listitem

    kb = xbmc.Keyboard('', 'Cerca su The Pirate Bay', False)
    kb.doModal()
    if not kb.isConfirmed():
        return

    query = kb.getText().strip()
    if not query:
        return

    # cat=200 = tutto il video, così i risultati sono già filtrati lato API
    url = API_SEARCH.format(query=quote_plus(query), cat='200')
    var.notify_dialog('The Pirate Bay', f'Cerca: {query}...', icon=var.addon_icon)

    data = _fetch_json(url)
    if not data:
        func.ok_dialog('Nessun risultato trovato.')
        return

    items = _build_items(data)
    if not items:
        func.ok_dialog(f'Nessun torrent video per: "{query}"')
        return
    for entry in items:
        build_listitem(entry)


# ─────────────────────────────────────────
# CATEGORIE
# ─────────────────────────────────────────

def show_cats():
    """Elenco categorie video. mode=tpb_cats"""
    for label, cat_id in CATEGORIES:
        func.create_listitem(Item(
            title=label,
            type='dir',
            mode='tpb_cat',
            link=cat_id,          # il dispatcher passa link come primo arg a show_cat
            thumbnail=var.addon_icon,
            is_media=False,
        ))


def show_cat(cat_id: str, title: str = ''):
    """
    Torrent di una categoria. mode=tpb_cat, link=cat_id numerico.

    apibay.org/q.php?q=&cat=X con query vuota restituisce sempre
    "No results returned". La strategia corretta è:
      1. Fetch data_top100_video.json (top 100 video, tutti)
      2. Filtra per campo 'category' == cat_id
      3. Se < 5 risultati, fallback su ricerca generica dell'anno corrente
    """
    from onion_xml_builder import build_listitem
    from datetime import datetime

    label = title or cat_id
    var.notify_dialog('The Pirate Bay', f'Carico {label}...', icon=var.addon_icon)

    # Step 1: top video con filtro categoria
    raw = _fetch_json(API_VIDEO)
    data = [item for item in raw if str(item.get('category', '')) == str(cat_id)]

    # Step 2: fallback — cerca anno corrente nella categoria
    if len(data) < 5:
        year = str(datetime.now().year)
        url_fb = API_SEARCH.format(query=year, cat=cat_id)
        data2 = _fetch_json(url_fb)
        # evita il finto risultato "No results returned"
        data2 = [i for i in data2 if i.get('id', '0') != '0']
        if data2:
            data = data2

    # Step 3: fallback finale — cerca titoli comuni nella categoria
    if len(data) < 5:
        for query in ('the', 'a', '2024', '2025'):
            url_fb2 = API_SEARCH.format(query=query, cat=cat_id)
            data3 = _fetch_json(url_fb2)
            data3 = [i for i in data3 if i.get('id', '0') != '0']
            if len(data3) >= 5:
                data = data3
                break

    if not data:
        func.ok_dialog('Nessun torrent trovato per questa categoria.')
        return

    items = _build_items(data)
    if not items:
        func.ok_dialog('Nessun torrent video trovato in questa categoria.')
        return
    for entry in items:
        build_listitem(entry)
