import os
import json
import subprocess
import urllib.request
from pathlib import Path
from rich.console import Console
from rich.table import Table

console = Console()

def safe_run(cmd, shell=False):
    subprocess.run(cmd, check=True, shell=shell)

def get_latest_version(name):
    """Obtém a versão mais recente de um pacote PyPI."""
    url = f"https://pypi.org/pypi/{name}/json"
    try:
        with urllib.request.urlopen(url, timeout=5) as response:
            data = json.load(response)
            return data["info"]["version"]
    except Exception:
        return None

def install_lib(name, version=None):
    base_dir = Path(__file__).resolve().parents[1]
    nfdos_dir = base_dir / "_nfdos"
    libs_dir = nfdos_dir / "libs"
    libs_dir.mkdir(parents=True, exist_ok=True)

    console.print(f"[cyan]📦 Instalando biblioteca:[/] {name} {version or ''}")
    cmd = f"pip download {name}{'==' + version if version else ''} -d {libs_dir}"
    safe_run(cmd, shell=True)

    # Registo no manifest
    manifest_path = libs_dir / "libs_manifest.json"
    manifest = json.loads(manifest_path.read_text()) if manifest_path.exists() else {}
    manifest[name] = {"version": version or "latest"}
    manifest_path.write_text(json.dumps(manifest, indent=4))
    console.print(f"[green]✔ {name} adicionada ao manifesto.[/green]")

def remove_lib(name):
    base_dir = Path(__file__).resolve().parents[1]
    libs_dir = base_dir / "_nfdos" / "libs"
    manifest_path = libs_dir / "libs_manifest.json"

    if not manifest_path.exists():
        console.print("[red]Nenhuma biblioteca instalada ainda.[/red]")
        return

    manifest = json.loads(manifest_path.read_text())

    if name not in manifest:
        console.print(f"[yellow]⚠ Biblioteca '{name}' não encontrada no manifesto.[/yellow]")
        return

    # Remover ficheiros relacionados
    removed = False
    for file in libs_dir.glob(f"{name}-*"):
        try:
            file.unlink()
            removed = True
        except Exception as e:
            console.print(f"[red]Erro ao remover {file}: {e}[/red]")

    # Atualizar manifest
    del manifest[name]
    manifest_path.write_text(json.dumps(manifest, indent=4))

    if removed:
        console.print(f"[green]✔ Biblioteca '{name}' removida com sucesso.[/green]")
    else:
        console.print(f"[yellow]⚠ Nenhum ficheiro físico encontrado para '{name}'.[/yellow]")

def update_lib(name):
    """Compara e atualiza biblioteca para a versão mais recente do PyPI."""
    base_dir = Path(__file__).resolve().parents[1]
    libs_dir = base_dir / "_nfdos" / "libs"
    manifest_path = libs_dir / "libs_manifest.json"

    if not manifest_path.exists():
        console.print("[red]Nenhuma biblioteca instalada ainda.[/red]")
        return

    manifest = json.loads(manifest_path.read_text())

    if name not in manifest:
        console.print(f"[yellow]⚠ Biblioteca '{name}' não está instalada.[/yellow]")
        return

    current_version = manifest[name].get("version")
    latest_version = get_latest_version(name)

    if not latest_version:
        console.print(f"[red]❌ Falha ao consultar PyPI para {name}.[/red]")
        return

    if current_version == latest_version or current_version == "latest":
        console.print(f"[green]✔ {name} já está na versão mais recente ({latest_version}).[/green]")
        return

    console.print(f"[yellow]🔄 Atualizando {name} ({current_version} → {latest_version})...[/yellow]")
    remove_lib(name)
    install_lib(name, latest_version)
    console.print(f"[green]✅ {name} atualizado para a versão {latest_version}.[/green]")

def list_libs():
    base_dir = Path(__file__).resolve().parents[1]
    libs_dir = base_dir / "_nfdos" / "libs"
    manifest_path = libs_dir / "libs_manifest.json"

    if not manifest_path.exists():
        console.print("[red]Nenhuma biblioteca instalada ainda.[/red]")
        return

    manifest = json.loads(manifest_path.read_text())
    table = Table(title="Bibliotecas do Neurotron")
    table.add_column("Nome", style="cyan")
    table.add_column("Versão", style="green")

    for name, data in manifest.items():
        table.add_row(name, data.get("version", "?"))

    console.print(table)

def run():
    while True:
        console.clear()
        console.rule("[bold yellow]📚 Bibliotecas do Neurotron[/bold yellow]")
        console.print("1. Instalar biblioteca")
        console.print("2. Listar bibliotecas instaladas")
        console.print("3. Atualizar biblioteca")
        console.print("4. Remover biblioteca")
        console.print("0. Voltar")

        choice = console.input("\n[cyan]nfdos> [/cyan]")

        if choice == "1":
            name = console.input("Nome da biblioteca: ")
            version = console.input("Versão (ou vazio p/ latest): ")
            install_lib(name, version or None)
        elif choice == "2":
            list_libs()
            console.input("\n[grey]Pressiona Enter para continuar...[/grey]")
        elif choice == "3":
            name = console.input("Nome da biblioteca: ")
            update_lib(name)
        elif choice == "4":
            name = console.input("Nome da biblioteca a remover: ")
            remove_lib(name)
        elif choice == "0":
            break
        else:
            console.print("[red]Opção inválida![/red]")

