<?php
namespace Nibiru\Module\Ai\Plugins;

/**
 * Chat completions. Talks to Ollama (default) or Anthropic (when configured).
 *
 *   $ai = new \Nibiru\Module\Ai\Ai();
 *   $reply = $ai->chat()->ask('How do I scaffold a module?');
 *
 *   // Multi-turn:
 *   $chat = $ai->chat();
 *   $chat->user('How do I scaffold a module?');
 *   $chat->user('And add Graylog hooks?');
 *   echo $chat->complete();
 *
 *   // Custom system + model:
 *   echo $ai->chat()
 *       ->system('Answer in German.')
 *       ->user('Explain MMVC.')
 *       ->model('qwen2.5-coder:14b')
 *       ->complete();
 */
class Chat
{
    protected \stdClass $cfg;
    protected Ollama $ollama;

    /** @var array<int, array{role:string,content:string}> */
    protected array $messages = [];

    protected ?string $modelOverride = null;
    protected ?float $temperature = null;
    protected ?int $maxTokens = null;
    protected ?string $systemPrompt = null;

    public function __construct(\stdClass $cfg)
    {
        $this->cfg = $cfg;
        $this->ollama = new Ollama($cfg);
        $this->systemPrompt = $cfg->chat_system_prompt ?? null;
    }

    public function system(string $prompt): self { $this->systemPrompt = $prompt; return $this; }
    public function model(string $name): self    { $this->modelOverride = $name; return $this; }
    public function temperature(float $t): self  { $this->temperature = $t; return $this; }
    public function maxTokens(int $n): self      { $this->maxTokens = $n; return $this; }

    public function user(string $content): self      { $this->messages[] = ['role' => 'user',      'content' => $content]; return $this; }
    public function assistant(string $content): self { $this->messages[] = ['role' => 'assistant', 'content' => $content]; return $this; }

    /**
     * Execute the chat call and return the assistant's reply text.
     * Appends the reply to the message history.
     */
    public function complete(): string
    {
        $apiMessages = [];
        if ($this->systemPrompt) {
            $apiMessages[] = ['role' => 'system', 'content' => $this->systemPrompt];
        }
        foreach ($this->messages as $m) {
            $apiMessages[] = $m;
        }

        $model = $this->modelOverride
            ?? ($this->cfg->chat_model ?? 'qwen2.5-coder:14b');
        $fallback = $this->cfg->chat_fallback_model ?? null;

        $opts = [
            'temperature' => $this->temperature ?? (float) ($this->cfg->chat_temperature ?? 0.4),
            'num_predict' => $this->maxTokens   ?? (int)   ($this->cfg->chat_max_tokens ?? 1024),
        ];

        try {
            $res = $this->ollama->chat($model, $apiMessages, $opts);
        } catch (\RuntimeException $e) {
            if ($fallback && $fallback !== $model) {
                $res = $this->ollama->chat($fallback, $apiMessages, $opts);
            } else {
                throw $e;
            }
        }

        $text = $res['message']['content'] ?? '';
        $this->assistant($text);
        return $text;
    }

    /**
     * One-shot helper — append a user message, complete, return reply.
     */
    public function ask(string $question): string
    {
        $this->user($question);
        return $this->complete();
    }

    /**
     * Reset the conversation (keeps system prompt + model override).
     */
    public function reset(): self
    {
        $this->messages = [];
        return $this;
    }

    /**
     * @return array<int, array{role:string,content:string}> the conversation
     */
    public function history(): array
    {
        return $this->messages;
    }
}
