<?php
namespace boru\boruai;

use boru\boruai\Models\Configuration;
use boru\dot\Dot;
use boru\boruai\Openai\OpenAIAssistant;
use boru\boruai\Openai\Models\Prompt;
use boru\output\Output;

class Config {
    private static $schemaVersion = 4;
    /** @var Configuration */
    private static $configuration;
    private static $hasConfiguration = false;
    private static $init = false;

    //Aliases
    public static function db() {
        return BoruAI::db();
    }
    public static function redis() {
        return BoruAI::redis();
    }
    public static function vectorPrefix() {
        return static::get("redis.vectorPrefix","boruai:vector:");
    }


    //Main functions

    public static function Configuration($configFile=null) {
        if($configFile) {
            if(is_string($configFile)) {
                $config = new Configuration($configFile);
                static::$configuration = $config;
            } elseif(is_array($configFile)) {
                $config = new Configuration(null,$configFile);
                static::$configuration = $config;
            } elseif($configFile instanceof Configuration) {
                static::$configuration = $configFile;
            }
        }
        if(!static::$configuration) {
            static::$configuration = new Configuration();
        }
        return static::$configuration;
    }
    public static function get($key=null,$default=null) {
        $configFile = static::Configuration();
        return $configFile->get($key,$default);
    }
    public static function set($key,$value) {
        $configFile = static::Configuration();
        return $configFile->set($key,$value);
    }
    public static function delete($key) {
        $configFile = static::Configuration();
        return $configFile->delete($key);
    }
    public static function save() {
        $configFile = static::Configuration();
        return $configFile->save();
    }

    public static function init($configFile="config.json",$createIfMissing=false) {
        
        if(!static::$init) {
            static::loadConfig($configFile,$createIfMissing);
            static::createTables();
            static::$init = true;
        }
    }

    private static function loadConfig($fileName,$createIfMissing=false) {
        if(!file_exists($fileName)) {
            if($createIfMissing) {
                static::$hasConfiguration = true;
                static::Configuration($fileName);
            } else {
                return;
            }
        } else {
            static::Configuration($fileName);
            static::$hasConfiguration = true;
        }
    }
    public static function loadManualConfig($config) {
        if(!is_array($config)) {
            $config = json_decode($config,true);
            if(!is_array($config)) {
                throw new \Exception("Config is not an array");
            }
        }
        static::Configuration()->merge($config);
        static::createTables();
        static::$init = true;
        //static::save();
    }
    
    private static function createTables() {
        $db = BoruAI::db();
        if($db !== false) {
            foreach(static::$tableSchemas as $tableBase => $schema) {
                $table = static::get("tables.".$tableBase);
                $schema = str_replace("{{TABLE}}", $table, $schema);
                $db->query($schema, []);
            }
            static::schemaCheck();
        }
    }

    private static function schemaCheck() {
        $schema = static::get("schema",0);
        if($schema < static::$schemaVersion) {
            if(BoruAI::isCLI()) {
                Output::outLine("Updating schema from $schema to ".static::$schemaVersion);
            }
            static::updateSchema($schema);
        }
    }
    private static function updateSchema($schema) {
        $db = BoruAI::db();
        if($db !== false) {
            /*if($schema < 1) {
                if(BoruAI::isCLI()) {
                    Output::outLine("Updating schema to version 1");
                }
                $table = static::get("tables.pages");
                $db->query("ALTER TABLE `$table` ADD COLUMN `content` longtext DEFAULT NULL", []);
                $db->query("ALTER TABLE `$table` CHANGE `summarized` `processed` DATETIME NULL", []);
                $schema = 1;
            }*/
            if($schema < 4) {
                if(BoruAI::isCLI()) {
                    Output::outLine("Updating schema to version 4");
                }
                $table = static::get("tables.files");
                $db->query("ALTER TABLE `$table` ADD COLUMN `reference` varchar(100) DEFAULT NULL AFTER `docid`", []);
                $schema = 4;
            }
            static::set("schema",static::$schemaVersion);
            static::save();
        }
    }

    private static $tableSchemas = [
        "files"=> "CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint(20) NOT NULL AUTO_INCREMENT,
            `path` varchar(255) DEFAULT NULL,
            `fileid`varchar(100) DEFAULT NULL,
            `docid` bigint(20) DEFAULT NULL,
            `reference` varchar(100) DEFAULT NULL,
            `object` varchar(100) DEFAULT 'file',
            `created_at` datetime DEFAULT NULL,
            `filename` varchar(255) DEFAULT NULL,
            `purpose` varchar(100) DEFAULT NULL,
            `bytes` int(9) DEFAULT NULL,
            `md5` varchar(40) DEFAULT NULL,
            `ocr_content` longtext DEFAULT NULL,
            `ocr_date` datetime DEFAULT NULL,
            `ocr_tokens` bigint NOT NULL DEFAULT '0',
            PRIMARY KEY (`id`),
            KEY `idx1` (`fileid`),
            KEY `idx2` (`md5`,`bytes`),
            KEY `idx3` (`docid`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ",
        "documents" => "CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint(20) NOT NULL AUTO_INCREMENT,
            `purpose` varchar(100) DEFAULT 'assistants',
            `reference` varchar(100) DEFAULT NULL,
            `filename` varchar(255) DEFAULT NULL,
            `pages` int(3) DEFAULT NULL,
            `filesize` int(9) DEFAULT NULL,
            `md5` varchar(40) DEFAULT NULL,
            `created` datetime DEFAULT NULL,
            `userid` bigint(20) DEFAULT NULL,
            `paged` datetime DEFAULT NULL,
            `summarized` datetime DEFAULT NULL,
            `summary` longtext DEFAULT NULL,
            `parsed` datetime DEFAULT NULL,
            `results` longtext DEFAULT NULL,
            `ocr_type` varchar(100) NOT NULL DEFAULT 'page',
            PRIMARY KEY (`id`),
            KEY `idx1` (`paged`),
            KEY `idx2` (`summarized`),
            KEY `idx3` (`created`,`userid`),
            KEY `idx4` (`md5`,`pages`,`filesize`),
            KEY `idx5` (`parsed`),
            KEY `idx6` (`reference`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ",
        "assistants" => "CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` varchar(255) NOT NULL,
            `object` varchar(100) DEFAULT 'assistant',
            `tag` varchar(100) DEFAULT NULL,
            `model` varchar(30) DEFAULT 'gpt-4o',
            `name` varchar(255) DEFAULT NULL,
            `description` longtext,
            `instructions` longtext,
            `tools` longtext,
            `file_ids` longtext,
            `metadata` longtext,
            PRIMARY KEY (`id`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ",
        "tools" => "CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint NOT NULL AUTO_INCREMENT,
            `type` varchar(100) DEFAULT 'function',
            `assistant_id` varchar(255) DEFAULT NULL,
            `name` varchar(255) DEFAULT NULL,
            `description` longtext,
            `callable` varchar(255) DEFAULT NULL,
            `parameters` longtext,
            `strict` int NOT NULL DEFAULT '1',
            PRIMARY KEY (`id`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ",
        "prompts"=> "CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint NOT NULL AUTO_INCREMENT,
            `assistant_id` varchar(255) DEFAULT NULL,
            `name` varchar(255) DEFAULT NULL,
            `description` longtext,
            `order` int NOT NULL DEFAULT '0',
            `prompt` longtext,
            PRIMARY KEY (`id`),
            KEY `idx1` (`assistant_id`,`order`),
            KEY `idx2` (`assistant_id`,`name`),
            KEY `idx3` (`assistant_id`,`name`,`order`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ",
        "sessions"=>"CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint NOT NULL AUTO_INCREMENT,
            `model` varchar(100) DEFAULT 'gpt-4o',
            `name` varchar(255) DEFAULT NULL,
            `created` datetime DEFAULT NULL,
            `updated` datetime DEFAULT NULL,
            `active` int NOT NULL DEFAULT '1',
            `important` longtext,
            `messages` longtext,
            PRIMARY KEY (`id`),
            KEY `idx1` (`name`,`active`),
            KEY `idx2` (`name`,`updated`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ",
        "queue"=>"CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint NOT NULL AUTO_INCREMENT,
            `action` varchar(100) DEFAULT 'ocr',
            `entity` varchar(255) DEFAULT NULL,
            `entityid` bigint DEFAULT NULL,
            `status` int NOT NULL DEFAULT '0',
            `enqueued` datetime DEFAULT NULL,
            `dequeued` datetime DEFAULT NULL,
            `options` longtext,
            PRIMARY KEY (`id`),
            KEY `idx2` (`action`,`status`,`enqueued`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ",
        "embeddings"=>"CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint NOT NULL AUTO_INCREMENT,
            `created` varchar(100) DEFAULT 'embedding',
            `md5` varchar(40) DEFAULT NULL,
            `query` varchar(255) DEFAULT NULL,
            `vector` longtext,
            PRIMARY KEY (`id`),
            KEY `idx1` (`query`),
            KEY `idx2` (`md5`),
            KEY `idx3` (`created`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ",
        "templates"=>"CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint NOT NULL AUTO_INCREMENT,
            `name` varchar(255) NOT NULL,
            `version` int(11) NOT NULL DEFAULT '1',
            `current` int(11) NOT NULL DEFAULT '0',
            `created_at` datetime DEFAULT NULL,
            `instructions` longtext,
            `prompt` longtext,
            `output` longtext,
            `tools` longtext,
            `files` longtext,
            PRIMARY KEY (`id`),
            KEY `idx_name_current` (`name`,`current`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
        ",
        "templateHistory"=>"CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint(19) NOT NULL AUTO_INCREMENT,
            `created_at` datetime DEFAULT NULL,
            `prompt_id` bigint(19) DEFAULT NULL,
            `version` int(11) NOT NULL DEFAULT '0',
            `reference_type` varchar(100) DEFAULT NULL,
            `reference_id` bigint(11) NOT NULL DEFAULT '0',
            `reference_stringid` varchar(255) NOT NULL DEFAULT '',
            `response` longtext,
            `prompt` longtext,
            PRIMARY KEY (`id`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
          ",
          "responses"=>"CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint(19) NOT NULL AUTO_INCREMENT,
            `user` bigint(19) DEFAULT 0,
            `reference` varchar(255) DEFAULT '',
            `template_id` bigint(19) DEFAULT 0,
            `created_at` datetime DEFAULT NULL,
            `model` varchar(100) DEFAULT NULL,
            `response_id` varchar(255) DEFAULT NULL,
            `input` longtext DEFAULT NULL,
            `output` longtext DEFAULT NULL,
            `result` longtext DEFAULT NULL,
            `compressed_input` longtext DEFAULT NULL,
            PRIMARY KEY (`id`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
          ",
          "responseGroups"=>"CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint(19) NOT NULL AUTO_INCREMENT,
            `user` bigint(19) DEFAULT 0,
            `reference` varchar(255) DEFAULT '',
            `created_at` datetime DEFAULT NULL,
            `updated_at` datetime DEFAULT NULL,
            `instructions` longtext DEFAULT NULL,
            `information` longtext DEFAULT NULL,
            `tools` longtext DEFAULT NULL,
            `last_response` varchar(255) DEFAULT NULL,
            PRIMARY KEY (`id`),
            KEY `userrefidx` (`user`,`reference`),
            KEY `refresponse` (`reference`,`last_response`),
            KEY `updatedidx` (`id`,`updated_at`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
          ",
          "collections"=>"CREATE TABLE IF NOT EXISTS `{{TABLE}}` (
            `id` bigint(19) NOT NULL AUTO_INCREMENT,
            `collection` varchar(100) DEFAULT NULL,
            `record_id` bigint(19) DEFAULT NULL,
            `string_id` varchar(255) DEFAULT NULL,
            `uid` varchar(100) DEFAULT NULL,
            `synced` datetime DEFAULT NULL,
            `vector` longtext DEFAULT NULL,
            `payload` longtext DEFAULT NULL,
            PRIMARY KEY (`id`),
            KEY `id1` (`collection`,`record_id`,`synced`),
            KEY `stringid` (`collection`,`string_id`,`synced`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
          ",
    ];

    public static function defaultConfig() {
        $version = static::$schemaVersion;
        return [
            "schema" => $version,
            "openai" => [
                "api_key" => ""
            ],
            "defaultModels" => [
                "default" => "gpt-4.1",
                "sessionCompress" => "gpt-4.1-mini",
                "embedding" => "text-embedding-3-small",
            ],
            "outputdir" => __DIR__."/../output/",
            "tables" => [
                "files" => "boru_ai_files",
                "documents" => "boru_ai_documents",
                "assistants" => "boru_ai_assistants",
                "tools" => "boru_ai_tools",
                "prompts" => "boru_ai_prompts",
                "sessions" => "boru_ai_sessions",
                "queue" => "boru_ai_queue",
                "embeddings" => "boru_ai_embeddings",
                "templates" => "boru_ai_templates",
                "templateHistory" => "boru_ai_template_history",
                "responses" => "boru_ai_responses",
                "responseGroups" => "boru_ai_response_groups",
                "collections" => "boru_ai_collections",
            ],
            "dbconfig" => [
                "use" => false,
                "dbhost" => "localhost",
                "dbport" => 3306,
                "dbname" => "",
                "dbuser" => "",
                "dbpass" => "",
                "dbtype" => "mysql",
            ],
            "redis" => [
                "scheme" => "tcp",
                "host" => "127.0.0.1",
                "port" => 6379,
                "auth" => "",
                "vectorPrefix" => "boruai:vector:",
            ],
            "qdrant" => [
                "host" => "localhost",
                "apiPort" => 6333,
                "apiKey" => false,
                "docker"=>[
                    "image"=>"qdrant/qdrant",
                    "name"=>"qdrant",
                    "apiPort"=>6333,
                    "grpcPort"=>6334,
                    "dataPath"=>"/var/lib/qdrant",
                ]
            ],
            "ocrspace" => [
                "api_key" => "",
                "url" => "https://api.ocr.space/parse/image",
                "engine" => 2,
                "max_file_size_megs" => 1,
            ],
            "threaderOptions" => [
                "bootstrapFile" => "",
                "numWorkers" => 2,
                "maxQueued"=> 100,
            ],
            "embeddings" => [
                'model' => "text-embedding-ada-002",
                "cache" => [
                    "expire" => 3*24*60*60, //3days
                    "max_length" => 200,
                ],
            ],
            "vtiger" => [
                "root_dir" => "",
            ],
            "web" => [
                "enabled" => false,
            ],
            "socket" => [
                "url_base" => "http://localhost/",
                "auth" => "",
                "socket_port" => 5000,
                "api_port" => 5001,
            ],
            "mcp_url" => "",
        ];
    }
}
