<?php
defined('ABSPATH') || exit;

if (!class_exists('Aimogen_API')) {

class Aimogen_API {

    public function ask($prompt, $args = array()) {
        return $this->run($prompt, wp_parse_args($args, array(
            'mode'    => 'text',
            'is_chat' => true,
            'env'     => 'phpApiAsk',
        )));
    }

    public function see($prompt, $image_url, $args = array()) {
        $args['vision_file'] = $image_url;
        $args['is_chat'] = true;
        $args['env'] = isset($args['env']) ? $args['env'] : 'phpApiSee';

        return $this->run($prompt, $args);
    }

    public function extract($prompt, $schema = array(), $args = array()) {
        $schema_text = '';

        if (!empty($schema)) {
            $schema_text = "\n\nReturn only valid JSON matching this structure:\n" . wp_json_encode($schema);
        } else {
            $schema_text = "\n\nReturn only valid JSON. Do not wrap it in markdown. Do not add explanations.";
        }

        $result = $this->run($prompt . $schema_text, wp_parse_args($args, array(
            'mode'    => 'json',
            'is_chat' => true,
            'env'     => 'phpApiExtract',
        )));

        if ($result->failed()) {
            return $result;
        }

        $raw = trim($result->text());
        $raw = preg_replace('/^```json\s*/i', '', $raw);
        $raw = preg_replace('/^```\s*/', '', $raw);
        $raw = preg_replace('/\s*```$/', '', $raw);

        $data = json_decode($raw, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            return new Aimogen_Response(false, null, 'Invalid JSON returned by Aimogen: ' . json_last_error_msg(), array(
                'raw' => $raw,
            ));
        }

        return new Aimogen_Response(true, $data, '', $result->meta());
    }

    public function paint($prompt, $args = array()) {
        if (!function_exists('aiomatic_generate_ai_image')) {
            return new Aimogen_Response(false, null, 'Aimogen image generation is not available.');
        }

        $settings = get_option('aiomatic_Main_Settings', false);
        $token = $this->get_openai_token($settings);

        $number = isset($args['number']) ? absint($args['number']) : 1;
        $size = isset($args['size']) ? sanitize_text_field($args['size']) : '1024x1024';
        $env = isset($args['env']) ? sanitize_text_field($args['env']) : 'phpApiPaint';
        $nocopy = isset($args['nocopy']) ? (bool) $args['nocopy'] : false;
        $model = isset($args['model']) ? sanitize_text_field($args['model']) : 'gpt-image-2';
        $file_name = isset($args['file_name']) ? sanitize_file_name($args['file_name']) : '';

        $error = '';

        $image = aiomatic_generate_ai_image(
            $token,
            $number,
            $prompt,
            $size,
            $env,
            $nocopy,
            0,
            $error,
            $model,
            $file_name
        );

        if ($image === false) {
            return new Aimogen_Response(false, null, $error);
        }

        return new Aimogen_Response(true, $image, '', array(
            'model' => $model,
            'size'  => $size,
            'env'   => $env,
        ));
    }

    public function thread($thread_id = '') {
        if ($thread_id === '') {
            $thread_id = wp_generate_uuid4();
        }

        return new Aimogen_Thread($this, $thread_id);
    }

    public function agent($assistant_id) {
        return new Aimogen_Agent($this, $assistant_id);
    }

    public function run($prompt, $args = array()) {
        if (!function_exists('aiomatic_generate_text')) {
            return new Aimogen_Response(false, null, 'Aimogen text generation is not available.');
        }

        $settings = get_option('aiomatic_Main_Settings', false);

        if (!aiomatic_check_api_keys($settings)) {
            return new Aimogen_Response(false, null, 'No AI API key is configured in Aimogen Pro settings.');
        }

        $model = $this->get_model($settings, $args);
        $token = $this->get_openai_token($settings);

        $available_tokens = $this->get_available_tokens($model, $prompt, $args);

        $temperature = isset($args['temperature']) ? floatval($args['temperature']) : 1;
        $top_p = isset($args['top_p']) ? floatval($args['top_p']) : 1;
        $presence_penalty = isset($args['presence_penalty']) ? floatval($args['presence_penalty']) : 0;
        $frequency_penalty = isset($args['frequency_penalty']) ? floatval($args['frequency_penalty']) : 0;

        $is_chat = isset($args['is_chat']) ? (bool) $args['is_chat'] : true;
        $env = isset($args['env']) ? sanitize_text_field($args['env']) : 'phpApiRun';

        $assistant_id = isset($args['assistant_id']) ? $args['assistant_id'] : '';
        $assistant_id = isset($args['assistantId']) ? $args['assistantId'] : $assistant_id;

        $thread_id = isset($args['thread_id']) ? sanitize_text_field($args['thread_id']) : '';
        $thread_id = isset($args['threadId']) ? sanitize_text_field($args['threadId']) : $thread_id;

        $vision_file = isset($args['vision_file']) ? esc_url_raw($args['vision_file']) : '';
        $user_question = isset($args['user_question']) ? sanitize_text_field($args['user_question']) : '';
        $role = isset($args['role']) ? sanitize_key($args['role']) : 'user';

        $embedding_namespace = isset($args['embedding_namespace']) ? sanitize_text_field($args['embedding_namespace']) : '';
        $function_result = isset($args['function_result']) ? $args['function_result'] : '';
        $file_data = isset($args['file_data']) ? $args['file_data'] : '';
        $parse_markdown = isset($args['parse_markdown']) ? (bool) $args['parse_markdown'] : false;
        $store_data = isset($args['store_data']) ? (bool) $args['store_data'] : false;
        $forced_functions = isset($args['functions']) && is_array($args['functions']) ? $args['functions'] : array();
        $enabled_mcp_servers = isset($args['mcp_servers']) ? $args['mcp_servers'] : '';

        $no_internet = isset($args['internet']) && $args['internet'] === false;
        $no_embeddings = isset($args['embeddings']) && $args['embeddings'] === false;
        $stream = isset($args['stream']) ? (bool) $args['stream'] : false;

        $finish_reason = '';
        $error = '';

        $text = aiomatic_generate_text(
            $token,
            $model,
            $prompt,
            $available_tokens,
            $temperature,
            $top_p,
            $presence_penalty,
            $frequency_penalty,
            $is_chat,
            $env,
            0,
            $finish_reason,
            $error,
            $no_internet,
            $no_embeddings,
            $stream,
            $vision_file,
            $user_question,
            $role,
            $assistant_id,
            $thread_id,
            $embedding_namespace,
            $function_result,
            $file_data,
            $parse_markdown,
            $store_data,
            $forced_functions,
            $enabled_mcp_servers
        );

        if ($text === false) {
            return new Aimogen_Response(false, null, $error);
        }

        return new Aimogen_Response(true, $text, '', array(
            'model'         => $model,
            'env'           => $env,
            'finish_reason' => $finish_reason,
            'thread_id'     => $thread_id,
        ));
    }

    private function get_model($settings, $args) {
        if (isset($args['model']) && trim($args['model']) !== '') {
            $model = trim($args['model']);
        } else {
            $model = aiomatic_get_default_model_name($settings);
        }

        $all_models = aiomatic_get_all_models(true);

        if (!in_array($model, $all_models, true)) {
            $model = aiomatic_get_default_model_name($settings);
        }

        return $model;
    }

    private function get_available_tokens($model, $prompt, $args) {
        $max_tokens = aimogenpro_get_max_tokens($model);
        $prompt_text = $this->prompt_to_text($prompt);

        $query_token_count = count(aiomatic_encode($prompt_text));

        $available_tokens = aiomatic_compute_available_tokens(
            $model,
            $max_tokens,
            $prompt_text,
            $query_token_count
        );

        if (isset($args['tokens']) && is_numeric($args['tokens'])) {
            $available_tokens = min($available_tokens, absint($args['tokens']));
        }

        if (isset($args['max_tokens']) && is_numeric($args['max_tokens'])) {
            $available_tokens = min($available_tokens, absint($args['max_tokens']));
        }

        return max(1, $available_tokens);
    }

    private function prompt_to_text($prompt) {
        if (is_string($prompt)) {
            return $prompt;
        }

        if (!is_array($prompt)) {
            return '';
        }

        $text = '';

        foreach ($prompt as $message) {
            if (!is_array($message)) {
                continue;
            }

            if (isset($message['role'])) {
                $text .= $message['role'] . ': ';
            }

            if (isset($message['content'])) {
                if (is_string($message['content'])) {
                    $text .= $message['content'] . "\n";
                }
            }
        }

        return trim($text);
    }

    private function get_openai_token($settings) {
        if (!isset($settings['app_id'])) {
            return '';
        }

        $appids = preg_split('/\r\n|\r|\n/', trim($settings['app_id']));
        $appids = array_filter($appids);

        if (empty($appids)) {
            return '';
        }

        $token = $appids[array_rand($appids)];

        $token = apply_filters('aimogen_openai_api_key', $token);
        $token = apply_filters('aiomatic_openai_api_key', $token);

        return $token;
    }
}

}