<?php
namespace boru\boruai\Cli\Defs\Openai;

use boru\cli\CLI;
use boru\cli\params\Flag;
use boru\cli\params\Option;
use boru\cli\params\Positional;
use boru\output\Output;
use boru\boruai\Openai\Api\Endpoints\AssistantsAPI;
use boru\boruai\Openai\OpenAIAssistant;

trait AssistantCLI {
    public static function def_openai_assistant() {
        return [
            "description"=> "Assistant Operations",
            "params" => [
                //Positional::create("command|The command to execute",["options"=>["list","get","create","update","delete"]]),
            ]
        ];
    }

    public static function def_openai_assistant_list() {
        return [
            "description"=> "List Assistants",
            "params" => [
            ]
        ];
    }
    public function cmd_openai_assistant_list($cmd) {
        $assistants = AssistantsAPI::listAssistants();
        foreach($assistants as $assistant) {
            Output::outLine($assistant->id(),"\t",$assistant->name());
        }
    }

    public static function def_openai_assistant_get() {
        return [
            "description"=> "Get Assistant",
            "params" => [
                Positional::create("assistant|Assistant ID or Name"),
                Flag::create("db|Get the assistant from the database"),
                Option::create("f|file|The file to write the assistant to"),
            ]
        ];
    }
    public function cmd_openai_assistant_get($cmd) {
        $assistantInput = $this->get("assistant");

        $assistant = OpenAIAssistant::fromOpenAI($assistantInput);
        
        if($assistant) {
            $outFile = $this->get("file",false);
            if($outFile) {
                $assistant->toFile($outFile);
            }
            $data=json_encode($assistant->toArray(),JSON_PRETTY_PRINT);
            Output::outLine($data);
        } else {
            Output::outLine("Assistant",$assistantInput,"not found");
        }
    }

    public static function def_openai_assistant_create() {
        return [
            "description"=> "Create Assistant",
            "params" => [
                Flag::create("i|noninteractive|Run in non-interactive mode"),
                Option::create("f|file|The file to read from.. <assistant> must be the ID of the assistant to update"),
                Option::create("n|name|The name of the assistant"),
                Option::create("m|model|The model to use for the assistant",["default"=>"gpt-4o"]),
                Flag::create("filesearch|Enable the file search tool"),
                Flag::create("codeinterpreter|Enable the code interpreter tool"),
            ]
        ];
    }
    public function cmd_openai_assistant_create($cmd) {
        $nonInteractive = $this->get("noninteractive",false);
        if(($assistantFile = $this->get("file",false))) {
            if(file_exists($assistantFile)) {
                $assistant = OpenAIAssistant::fromFile($assistantFile);
            } else {
                throw new \Exception("Assistant JSON file is required to update assistant when using the -f|--file option");
            }
        } else {
            $assistant = new OpenAIAssistant();
        }
        if(($name = $this->get("name",false))!==false) {
            $assistant->name($name);
        } elseif($nonInteractive) {
            $name = $assistant->name();
            if(!$name) {
                throw new \Exception("Name is required in non-interactive mode");
            }
        } else {
            $name = $assistant->name();
            if($name) {
                Output::outLine("Name:",$name);
                $newName = CLI::promptInput("Enter a new name, or press return to keep: ");
                if($newName) {
                    $name = $newName;
                }
            } else {
                $name = CLI::promptInput("Name: ");
            }
        }

        if(($model = $this->get("model",false))!==false) {
            $assistant->model($model);
        } elseif($nonInteractive) {
            $model = $assistant->model();
            if(!$model) {
                throw new \Exception("Model is required in non-interactive mode");
            }
        } else {
            $model = $assistant->model();
            if($model) {
                Output::outLine("Model:",$model);
                $newModel = CLI::promptInput("Enter a new model, or press return to keep: ");
                if($newModel) {
                    $model = $newModel;
                }
            } else {
                $model = CLI::promptInput("Model: ");
            }
        }

        if(!$nonInteractive) {
            $instructions = trim($assistant->instructions());
            $assistant->instructions(trim(CLI::edit($instructions)));
        }

        if($this->get("filesearch",false)) {
            $assistant->addTool("file_search");
        }
        if($this->get("codeinterpreter",false)) {
            $assistant->addTool("code_interpreter");
        }
        $assistant->save();
    }

    public static function def_openai_assistant_update() {
        return [
            "description"=> "Update Assistant",
            "params" => [
                Positional::create("assistant|Assistant ID or Name"),
                Option::create("f|file|The file to read from.. <assistant> must be the ID of the assistant to update"),
            ]
        ];
    }
    public function cmd_openai_assistant_update($cmd) {
        $assistantInput = $this->get("assistant");
        if(($assistantFile = $this->get("file",false))) {
            if(file_exists($assistantFile)) {
                $assistant = OpenAIAssistant::fromFile($assistantFile);
                $assistant->id($assistantInput);
            } else {
                throw new \Exception("Assistant JSON file is required to update assistant when using the -f|--file option");
            }
        } else {
            $assistant = OpenAIAssistant::fromId($assistantInput);
        }
        if($assistant) {
            $assistant->save();
            Output::outLine("Assistant",$assistant->id(),"updated");
        }
    }

    public static function def_openai_assistant_edit() {
        return [
            "description"=> "Update Assistant",
            "params" => [
                Positional::create("assistant*|Assistant ID or Name"),
                Positional::create("attribute*|The attribute to update",["options"=>["name","description","instructions"]]),
            ]
        ];
    }
    public function cmd_openai_assistant_edit($cmd) {
        $assistantInput = $this->get("assistant");
        $assistant = OpenAIAssistant::fromId($assistantInput);
        if(!$assistant) {
            Output::outLine("Assistant",$assistantInput,"not found");
            return;
        }
        $attribute = $this->get("attribute");
        if(!in_array($attribute,["name","description","instructions","filesearch","codeinterpreter"])) {
            Output::outLine("Attribute",$attribute,"not found");
            return;
        }
        if($attribute == "filesearch") {
            $added = false;
            if($assistant->hasTool("file-search")) {
                $assistant->removeTool("file-search");
            } else {
                $assistant->addTool("file-search");
                $added = true;
            }
            $assistant->save();
            Output::outLine("Assistant",$assistant->id(),"updated");
            if($added) {
                Output::outLine("Added","file-search");
            } else {
                Output::outLine("Removed","file-search");
            }
            return;
        }
        if($attribute == "codeinterpreter") {
            $added = false;
            if($assistant->hasTool("code-interpreter")) {
                $assistant->removeTool("code-interpreter");
            } else {
                $assistant->addTool("code-interpreter");
                $added = true;
            }
            $assistant->save();
            Output::outLine("Assistant",$assistant->id(),"updated");
            if($added) {
                Output::outLine("Added","code-interpreter");
            } else {
                Output::outLine("Removed","code-interpreter");
            }
            return;
        }
        $original = trim(call_user_func([$assistant,$attribute]));
        $result = trim(CLI::edit($original));
        if($result != $original) {
            call_user_func_array([$assistant,$attribute],[$result]);
            $assistant->save();
            Output::outLine("Assistant",$assistant->id(),"updated");
            Output::outLine("Changed",$attribute);
            Output::outLine("From:",$original);
            Output::outLine("To:",$result);
        }
    }

    public static function def_openai_assistant_delete() {
        return [
            "description"=> "Delete Assistant",
            "params" => [
                Positional::create("*assistant+|one or more Assistants ID or Name"),
            ]
        ];
    }
    public function cmd_openai_assistant_delete($cmd) {
        $assistantInput = $this->get("assistant");
        foreach($assistantInput as $assistantInput) {
            $assistant = OpenAIAssistant::fromId($assistantInput);
            if($assistant) {
                $assistant->delete();
                Output::outLine("Assistant",$assistant->id(),"deleted");
            }
        }
    }
}