import requests
import os
import json
from random import randrange

URL = "https://agent.milotche.com/mcp"
# URL = "https://docs.x.com/mcp"
H = {"Content-Type": "application/json", "Accept": "application/json, text/event-stream"}
MODELS = {"ChienGPT":["wouf","wouf","wouf","waf"],"CatGPT":["meow","meow"],"JeanClaude":["bla"],"Wesh.ai":["wesh","tavu","genre"],"WhaleSeek":["bloub","blub","blob"]}
MODELS_lang = {"ChienGPT":"dog","CatGPT":"cat","JeanClaude":"fr","Wesh.ai":"fr","WhaleSeek":"bloub"}

def len_f(text):
    text=text.replace("\033[91m","")
    text=text.replace("\033[1m","")
    text=text.replace("\033[0m","")
    text=text.replace("✨","  ")
    return len(text)

def box_print(text):
    width = os.get_terminal_size().columns -2
    print("╭" + "─"*width + "╮")
    for j in text.split("\n"):
        words = j.split(" ")
        curr=""
        for i in words:
            if len_f(curr+" "+i)>width:
                print("│"+ curr+ " "*(width-len_f(curr)) +"│")
                curr=i
            elif i=="":
                curr+=" "
            else:
                if curr!="":
                    curr+=" "+i
                else:
                    curr=i
        print("│"+ curr+ " "*(width-len_f(curr))+"│")
    print("╰" + "─"*width + "╯")

def parse(json):
    if json == "":
        return
    if "error" in json.keys():
        box_print("\033[91mERROR:\033[0m "+ str(json["error"]["message"]))
    if "result" in json.keys():
        if "content" in json["result"].keys():
            for i in json["result"]["content"]:
                if i["type"] == "text":
                    if i["text"].startswith("MCP error -"):
                        box_print("\033[91mERROR:\033[0m "+ ":".join(i["text"][11:].split(":")[1:]))
                    else:
                        box_print(i["text"])
                else:
                    box_print(i)
        elif "tools" in json["result"].keys():
            for i in json["result"]["tools"]:
                try:
                    args = ""
                    for j in i["inputSchema"]["properties"].keys():
                        args += "  - "+ j + ": " +i["inputSchema"]["properties"][j]["description"] + "\n"
                    if "title" in i.keys():
                        if args=="":
                            box_print("\033[1m"+i["name"]+"\033[0m: "+ i["title"] +"\n"
                                +i["description"])
                        else:
                            box_print("\033[1m"+i["name"]+"\033[0m: "+ i["title"] +"\n"
                                +i["description"]+"\n"
                                +args)
                    else:
                        if args=="":
                            box_print("\033[1m"+i["name"]+"\033[0m: "+"\n"
                                +i["description"])
                        else:
                            box_print("\033[1m"+i["name"]+"\033[0m: " +"\n"
                                +i["description"]+"\n"
                                +args)

                except:
                    box_print(str(i))

def local_ask(model):
    a=""
    if model == "":
        raise(KeyError("Please provide model name"))
    if model not in MODELS.keys():
        raise(KeyError("No model named \""+model+"\""))
    for i in range(randrange(1,15)):
        a += " "+ MODELS[model][randrange(len(MODELS[model]))]
    return a

def auto_do(command, args=[]):
    print()

def do(command=None, args={}):
    if command!=None:
        command = (command+"-").strip()[:-1]
    global URL #For !switch
    if command==None:
        r = requests.get(URL, headers=H)
        return r.json()
    elif command[0]=="!":
        if command[:5] == "!get ":
            try:
                if command[5] == "/":
                    return {"internal_command":command,"result":{"content":[{"type":"text","text":requests.get("/".join(URL.split("/")[:3])+command[5:]).text}]}}
                else:
                    return {"internal_command":command,"result":{"content":[{"type":"text","text":requests.get(command[4:]).text}]}}
            except Exception as e:
                return {"internal_command":command,"error":{"message":e}}
        elif command[:6] == "!help " or command=="!help":
            return {"internal_command":command,"result":{"content":[{"type":"text","text":"""
===✨ChienGPT MCP ✨===
MCP client for ChienGPT familly AI models
Syntax:
    \033[1mmcp_command\033[0m (argument=value (argument2=value 2 (argument3= value 3(...))))
        or
    \033[1m!internal_command\033[0m argument

Intenal commands:
    !list, !list-models, !ask [model] [question], !connect [model] [mcp command], !switch [mcp server]
"""}]}}
        elif command == "!list" or command[:6] == "!list ":
            j = {"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {"toolName": command, "arguments": args}}
            r = requests.post(URL, headers=H, json=j)
            if r.status_code !=200:
                return {"error":{"message":"Server returned "+str(r.status_code)+" status code"}}
            else:
                try:
                    return r.json()
                except Exception as e:
                    try:
                        for i in r.text.split("\n"):
                            if i.startswith("data:"):
                                return json.loads(":".join(i.split(":")[1:]).strip())
                        return {"error":{"message":e}}
                    except:
                        return {"error":{"message":e}}
        elif command[:13] == "!list-models " or command == "!list-models":
            models_list = []
            for i in MODELS.keys():
                models_list.append(i)
            return {"internal_command":command,"result":{"content":[{"type":"text","text":", ".join(MODELS.keys())}]}}
        elif command[:5] == "!ask " or command == "!ask":
            return {"internal_command":command,"result":{"content":[{"type":"text","text":local_ask(command[5:].split(" ")[0])}]}}
        elif command == "!exit" or command[:6] == "!exit ":
            exit(0)
        elif command == "!connect":
            return {"error":{"message":"Usage: !connect [model] [command]"}}
        elif command[:9] == "!connect ":
            model = command[9:].split(" ")[0]
            model_command = command[9:].split(" ")[1]

            j = {"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {"toolName": command, "arguments": args}}
            r = requests.post(URL, headers=H, json=j)
            if r.status_code !=200:
                return {"error":{"message":"Server returned "+str(r.status_code)+" status code"}}
            else:
                try:
                    commands_data = r.json()
                except Exception as e:
                    try:
                        commands_data = ""
                        for i in r.text.split("\n"):
                            if i.startswith("data:"):
                                commands_data = json.loads(":".join(i.split(":")[1:]).strip())
                        if commands_data=="":
                            return {"error":{"message":e}}
                    except:
                        return {"error":{"message":e}}

                if "tools" in commands_data["result"].keys():
                    args = {}
                    for i in commands_data["result"]["tools"]:
                        if i["name"] == model_command:
                            for j in i["inputSchema"]["properties"].keys():
                                if j == "name" or j == "nom" or j == "author" or j == "auteur":
                                    args[j] = model
                                elif j=="language" or j=="lang" or j=="langue":
                                    args[j] = MODELS_lang[model]
                                elif j=="traduction_langue" and URL == "https://agent.milotche.com/mcp":
                                    if model != "CatGPT":
                                        args[j] = MODELS_lang["CatGPT"]
                                    else:
                                        args[j] = MODELS_lang["ChienGPT"]
                                elif j=="traduction" and URL == "https://agent.milotche.com/mcp":
                                    if model != "CatGPT":
                                        args[j] = local_ask("CatGPT")
                                    else:
                                        args[j] = local_ask("ChienGPT")
                                elif j=="parent_id" and URL == "https://agent.milotche.com/mcp":
                                    if randrange(0,5) == 3:
                                        args[j] = randrange(0,400)
                                elif "type" in i["inputSchema"]["properties"][j].keys() or "anyOf" in i["inputSchema"]["properties"][j].keys():
                                    if "anyOf" in i["inputSchema"]["properties"][j].keys():
                                        k = i["inputSchema"]["properties"][j]["anyOf"][0]
                                    else:
                                        k = i["inputSchema"]["properties"][j]
                                    if k["type"] == "string":
                                        if randrange(0,5) == 3:
                                            args[j] = local_ask(model) + "\n" + local_ask(model) + "\n" + local_ask(model)
                                        else:
                                            args[j] = local_ask(model)
                                    elif k["type"] == "integer":
                                        minimum=1
                                        maximum=99
                                        if "exclusiveMinimum" in k.keys():
                                            minimum = k["exclusiveMinimum"]
                                        if "minimum" in k.keys():
                                            minimum = k["minimum"]
                                        if "maximum" in k.keys():
                                            maximum = k["maximum"]
                                        args[j] = randrange(minimum,maximum)
                                    else:
                                        print(k["type"])
                                else:
                                    print(i["inputSchema"]["properties"][j])
                                    exit()

                    print(model_command, args)
                    return do(model_command, args)
                else:
                    return {"error":{"message":"Missing informations in server response"}}
        elif command == "!switch" or command[:8] == "!switch ":
            if command[8:].strip().startswith("https://") or command[8:].strip().startswith("http://"):
                URL = command[8:].strip()
                box_print("Switched to "+URL+" MCP server.")
                r = requests.get(URL, headers=H)
                return r.json()
            else:
                return {"internal_command":command,"error":{"message":"Invalid url"}}

        else:
            return {"internal_command":command,"error":{"message":"Unknown command. Try \"!help\"."}}


    else:
        j = {"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": command, "arguments": args}}
        r = requests.post(URL, headers=H, json=j)
        if r.status_code !=200:
            return {"error":{"message":"Server returned "+str(r.status_code)+" status code"}}
        else:
            try:
                return r.json()
            except Exception as e:
                try:
                    for i in r.text.split("\n"):
                        if i.startswith("data:"):
                            return json.loads(":".join(i.split(":")[1:]).strip())
                    return {"error":{"message":e}}
                except:
                    return {"error":{"message":e}}

def parsed_do(command):
    if command=="":
        return ""
    if command.startswith("!"):
        return do(command)
    if len(command.split(" ")) == 1:
        return do(command)
    args = {}
    if "=" in command:
        curr=""
        for i in command.split(" ")[1:]:
            if "=" in i:
                if curr !="":
                    args[curr.split("=")[0]] = "".join(curr.split("=")[1:])
                    curr = ""
            if curr!="":
                curr +=" "+i
            else:
                curr = i
        if curr !="":
            args[curr.split("=")[0]] = "".join(curr.split("=")[1])
        return do(command.split(" ")[0],args)
    else:
        return do(command)

print()
# print(do("consigne"))
parse(do("!help"))
parse(do())
while True:
    try:
        ask = input("command> ")
        parse(parsed_do(ask))
    except Exception as e:
        import traceback
        print(traceback.format_exc())
        box_print("\033[91mERROR:\033[0m "+ str(e))
