#!/usr/bin/env python3
"""Nexuus Connect — cliente de API para Windows, macOS e Linux. Python 3.10+."""
import argparse
import getpass
import json
import os
import sys
import time
from pathlib import Path
import urllib.error
import urllib.parse
import urllib.request


def main():
    parser = argparse.ArgumentParser(description="Converse com o Nexuus pela API da sua conta Pro.")
    parser.add_argument("message", nargs="?", help="Mensagem; sem este argumento, abre uma conversa interativa.")
    parser.add_argument("--api", default="https://ai.nexuus.com.br", help="Endereço da plataforma Nexuus.")
    parser.add_argument("--service", choices=["auto", "chat", "code", "analysis", "documents", "research"], default="auto")
    parser.add_argument("--project", type=int, help="ID do seu projeto para usar arquivos e histórico do Workspace.")
    parser.add_argument("--projects", action="store_true", help="Listar seus projetos.")
    parser.add_argument("--create", choices=["auto","pdf","xlsx","docx","pptx","web","code","saas","prompt","image","video","image_ai","video_ai"], help="Criar um arquivo no Estúdio do projeto.")
    parser.add_argument("--output", help="Caminho de destino do arquivo criado; não sobrescreve arquivos existentes.")
    args = parser.parse_args()
    if args.create and (not args.project or not args.message):
        parser.error("Use --create com --project e a descrição entre aspas.")
    if args.output and not args.create:
        parser.error("--output deve acompanhar --create.")
    url = urllib.parse.urlparse(args.api)
    if url.scheme != "https" and not (url.scheme == "http" and url.hostname in {"localhost", "127.0.0.1"}):
        parser.error("Use um endereço HTTPS para proteger sua chave de API.")
    base = args.api.rstrip("/")
    key = os.environ.get("NEXUUS_API_KEY") or getpass.getpass("Sua chave de API Nexuus: ")
    if not key.startswith("nx_"):
        parser.error("Crie uma chave em Downloads e API na plataforma Nexuus.")

    def request(path, data=None):
        headers = {"Authorization": "Bearer " + key, "Content-Type": "application/json"}
        payload = json.dumps(data).encode() if data is not None else None
        return urllib.request.urlopen(urllib.request.Request(base + path, data=payload, headers=headers), timeout=180)

    try:
        if args.projects:
            with request("/api/v1/projects") as result:
                for project in json.load(result)["projects"]:
                    print(f"{project['id']}: {project['name']}")
            return 0
        if args.create:
            with request(f"/api/v1/projects/{args.project}/artifacts", {"prompt": args.message, "kind": args.create}) as response:
                artifact=json.load(response)
            deadline=time.monotonic()+650
            last=None
            while artifact["status"] not in {"ready","failed"}:
                if artifact["message"]!=last:
                    last=artifact["message"];print(last,file=sys.stderr)
                if time.monotonic()>deadline:
                    raise RuntimeError(f"A criação {artifact['id']} continua em andamento. Acompanhe no Workspace.")
                time.sleep(3)
                with request(f"/api/v1/artifacts/{artifact['id']}") as response:
                    artifact=json.load(response)
            if artifact["status"]!="ready":raise RuntimeError(artifact["message"])
            print(f"Criação {artifact['id']}: {artifact['title']}")
            if args.output:
                primary=artifact["manifest"]["primary"]
                target=Path(args.output)
                with request(f"/api/v1/artifacts/{artifact['id']}/file?name="+urllib.parse.quote(primary,safe='')) as response:
                    with target.open("xb") as destination:
                        while chunk:=response.read(1024*1024):destination.write(chunk)
                print("Arquivo salvo em "+str(target))
            else:print("Abra o projeto na plataforma para visualizar ou baixar os arquivos.")
            return 0
        history = []
        if not args.message:
            print("Nexuus Connect · digite /sair para encerrar.\n")
        while True:
            message = args.message or input("Você: ").strip()
            if message in {"/sair", "/exit"}:
                return 0
            if not message:
                continue
            history.append({"role": "user", "content": message[:4000]})
            history = history[-11:]
            while sum(len(row["content"]) for row in history) > 16000:
                history = history[2:]
            payload = {"messages": history, "service": args.service}
            if args.project:
                payload["project_id"] = args.project
            reply, completed = "", False
            print("Nexuus: ", end="", flush=True)
            with request("/api/v1/invoke", payload) as response:
                for line in response:
                    if not line.strip():
                        continue
                    event = json.loads(line)
                    if event["type"] == "error":
                        raise RuntimeError(event["message"])
                    if event["type"] == "text":
                        reply += event["delta"]
                        print(event["delta"], end="", flush=True)
                    if event["type"] == "done":
                        completed = True
            print("\n")
            if not completed:
                raise RuntimeError("A resposta foi interrompida. Tente novamente.")
            history.append({"role": "assistant", "content": reply[:4000]})
            if args.message:
                return 0
    except urllib.error.HTTPError as error:
        try:
            message = json.load(error).get("detail", "Não foi possível concluir a solicitação.")
        except (ValueError, AttributeError):
            message = "Não foi possível concluir a solicitação."
        print("\nNexuus: " + str(message), file=sys.stderr)
        return 1
    except (urllib.error.URLError, RuntimeError, ValueError, OSError) as error:
        print("\nNexuus: " + str(error), file=sys.stderr)
        return 1
    except (KeyboardInterrupt, EOFError):
        print("\nConversa encerrada.")
        return 0


if __name__ == "__main__":
    raise SystemExit(main())
