#!/usr/bin/env python3
import requests
import argparse
import os
import sys

QBT_URL = "http://localhost:8080"
QBT_USER = "admin"
QBT_PASS = "Vocalize_Void_Rage_Visor_Ladies_Undercook_Spokesman_Fraternal"
TRACKERS_FILE = os.path.join(os.path.dirname(__file__), "private_trackers.txt")

session = requests.Session()

count_total = 0
count_private = 0
count_public = 0
count_ratio_updated = 0
count_label_added = 0
count_skipped = 0
count_no_tracker = 0
no_tracker_list = []

def login():
    r = session.post(f"{QBT_URL}/api/v2/auth/login", data={"username": QBT_USER, "password": QBT_PASS})
    if r.text != "Ok.":
        print("❌ Échec de la connexion à qBittorrent")
        sys.exit(1)
    print("✅ Connexion réussie à qBittorrent")

def get_private_trackers():
    if not os.path.isfile(TRACKERS_FILE):
        print(f"❌ Fichier introuvable : {TRACKERS_FILE}")
        sys.exit(1)
    with open(TRACKERS_FILE, "r", encoding="utf-8") as f:
        return [line.strip().lower() for line in f if line.strip() and not line.strip().startswith("#")]

def get_all_torrents():
    r = session.get(f"{QBT_URL}/api/v2/torrents/info")
    r.raise_for_status()
    return r.json()

def get_main_tracker(hash_):
    r = session.get(f"{QBT_URL}/api/v2/torrents/trackers", params={"hash": hash_})
    r.raise_for_status()
    trackers = r.json()
    for t in trackers:
        if t["url"].startswith("http"):
            return t["url"].lower()
    return ""

def has_label(torrent, label):
    tags = torrent.get("tags", "")
    return label in [t.strip() for t in tags.split(",") if t.strip()]

def set_label(hash_, label, dry_run):
    global count_label_added
    if dry_run:
        print(f"🏷️ [Dry-run] Would set label '{label}' on {hash_}")
    else:
        r = session.post(f"{QBT_URL}/api/v2/torrents/setLabel", data={
            "hashes": hash_,
            "label": label
        })
        if r.status_code == 200:
            print(f"🏷️ Label '{label}' appliqué sur {hash_}")
            count_label_added += 1
        else:
            print(f"❌ Erreur label sur {hash_}: {r.text}")

def tracker_is_private(tracker_url, private_patterns):
    return any(pat in tracker_url for pat in private_patterns)

def set_ratio(hash_, ratio, dry_run):
    global count_ratio_updated
    if dry_run:
        print(f"🧪 [Dry-run] ratio {ratio} would be set on {hash_}")
    else:
        r = session.post(f"{QBT_URL}/api/v2/torrents/setShareLimits", data={
            "hashes": hash_,
            "ratioLimit": ratio,
            "seedingTimeLimit": -1
        })
        if r.status_code == 200:
            print(f"✅ ratio {ratio} set on {hash_}")
            count_ratio_updated += 1
        else:
            print(f"❌ Erreur setting ratio on {hash_}: {r.text}")

def main():
    global count_total, count_private, count_public, count_skipped, count_no_tracker

    parser = argparse.ArgumentParser(description="qBittorrent Tracker Ratio Manager")
    parser.add_argument("--apply", action="store_true", help="Appliquer les changements")
    parser.add_argument("--default-ratio", type=float, default=1.0, help="Ratio à appliquer aux trackers publics (défaut: 1.0)")
    parser.add_argument("--summary", action="store_true", help="Afficher un résumé en fin de traitement")
    parser.add_argument("--label-private", default="ygg", help="Nom du label privé (défaut: ygg)")
    parser.add_argument("--label-public", default="public", help="Nom du label public (défaut: public)")
    args = parser.parse_args()

    login()
    private_patterns = get_private_trackers()
    torrents = get_all_torrents()
    dry_run = not args.apply
    ratio_public = args.default_ratio

    print(f"🔍 Traitement de tous les torrents")

    for torrent in torrents:
        count_total += 1

        name = torrent.get("name")
        hash_ = torrent.get("hash")
        current_ratio = torrent.get("max_ratio")
        tracker = get_main_tracker(hash_)

        if not tracker:
            print(f"❌ {name} : aucun tracker HTTP détecté")
            count_no_tracker += 1
            no_tracker_list.append(f"{name} ({hash_})")
            continue

        is_private = tracker_is_private(tracker, private_patterns)
        desired_ratio = -1 if is_private else ratio_public

        # Label management
        is_ygg = has_label(torrent, args.label_private)
        is_public = has_label(torrent, args.label_public)

        # Applique/affiche les actions sur le label
        if is_ygg:
            # rien à faire pour le label, mais on affiche
            pass
        else:
            # Si pas label ygg, on force label public
            if not is_public:
                set_label(hash_, args.label_public, dry_run)

        # Résumé stats
        if is_private:
            count_private += 1
        else:
            count_public += 1

        print(f"\n🎯 {name}\n   Tracker : {tracker}\n   Actuel  : {current_ratio}\n   Voulue  : {desired_ratio}")
        if str(current_ratio) == str(desired_ratio):
            print("↪️  Ratio déjà correct, rien à faire")
            count_skipped += 1
        else:
            set_ratio(hash_, desired_ratio, dry_run)

    if args.summary:
        print("\n📊 Résumé :")
        print(f"  🔍 Torrents traités   : {count_total}")
        print(f"  🔒 Privés (ratio -1)  : {count_private}")
        print(f"  🌍 Publics (ratio {ratio_public}) : {count_public}")
        print(f"  🚫 Sans tracker HTTP  : {count_no_tracker}")
        print(f"  🧪 Ratio modifiés     : {count_ratio_updated}")
        print(f"  ↪️ Déjà corrects       : {count_skipped}")
        print(f"  🏷️ Labels appliqués    : {count_label_added}")
        if count_no_tracker > 0:
            print("\n🚫 Liste des torrents sans tracker HTTP :")
            for line in no_tracker_list:
                print(f"   - {line}")

if __name__ == "__main__":
    main()