<?php
/**
 * class/chat.php — lógica del módulo de chat.
 *
 * Persiste conversaciones (chats / chats_messages) y habla con el proveedor LLM
 * upstream. La llamada al proveedor está aislada en askUpstream(): hoy hay un
 * stub; ahí se enchufa Claude/Gemini/etc. usando la key de $_config['llm'].
 */
if (!defined('IN_APP')) { die('Acceso denegado'); }

class Chat extends App
{
    public function __construct($db = null, $config = array())
    {
        parent::__construct($db, $config);
        $this->ensureSchema('chats');
        $this->ensureSchema('chats_messages');
    }

    /** Conversaciones del usuario, más recientes primero. */
    public function listChats($id_user)
    {
        $stmt = $this->db->prepare(
            'SELECT id_chat, title, updated_at FROM chats WHERE id_user = ? ORDER BY updated_at DESC LIMIT 100'
        );
        $stmt->bind_param('i', $id_user);
        $stmt->execute();
        $rows = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
        $stmt->close();
        return $rows;
    }

    /** Devuelve el chat si pertenece al usuario, o null. */
    public function getChat($id_chat, $id_user)
    {
        $stmt = $this->db->prepare('SELECT id_chat, title, model FROM chats WHERE id_chat = ? AND id_user = ? LIMIT 1');
        $stmt->bind_param('ii', $id_chat, $id_user);
        $stmt->execute();
        $row = $stmt->get_result()->fetch_assoc();
        $stmt->close();
        return $row ?: null;
    }

    /** Crea una conversación y devuelve su id. */
    public function createChat($id_user, $title = '', $model = null)
    {
        $model = $model ?: ($this->config['llm']['model'] ?? null);
        $stmt  = $this->db->prepare('INSERT INTO chats (id_user, title, model, created_at, updated_at) VALUES (?,?,?,NOW(),NOW())');
        $stmt->bind_param('iss', $id_user, $title, $model);
        $stmt->execute();
        $id = $this->db->insert_id;
        $stmt->close();
        return $id;
    }

    /** Mensajes de un chat (validando propiedad). */
    public function messages($id_chat, $id_user)
    {
        if (!$this->getChat($id_chat, $id_user)) return array();
        $stmt = $this->db->prepare('SELECT role, content, created_at FROM chats_messages WHERE id_chat = ? ORDER BY id_message ASC');
        $stmt->bind_param('i', $id_chat);
        $stmt->execute();
        $rows = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
        $stmt->close();
        return $rows;
    }

    /** Inserta un mensaje. */
    protected function addMessage($id_chat, $id_user, $role, $content, $model = null)
    {
        $stmt = $this->db->prepare(
            'INSERT INTO chats_messages (id_chat, id_user, role, content, model, created_at) VALUES (?,?,?,?,?,NOW())'
        );
        $stmt->bind_param('iisss', $id_chat, $id_user, $role, $content, $model);
        $stmt->execute();
        $stmt->close();
        $this->db->query('UPDATE chats SET updated_at = NOW() WHERE id_chat = ' . (int)$id_chat);
    }

    /**
     * Envía un mensaje del usuario: lo persiste, pide respuesta al upstream y la
     * persiste también. Crea el chat si no existe. Devuelve [id_chat, reply].
     */
    public function send($id_user, $id_chat, $text)
    {
        $text = trim((string)$text);
        if ($text === '') { $this->_error = App::t('chat.empty'); return null; }

        if (!$id_chat || !$this->getChat($id_chat, $id_user)) {
            $title   = mb_substr($text, 0, 60);
            $id_chat = $this->createChat($id_user, $title);
        }

        $model = $this->config['llm']['model'] ?? null;
        $this->addMessage($id_chat, $id_user, 'user', $text, null);

        $history = $this->messages($id_chat, $id_user);
        $reply   = $this->askUpstream($history);

        $this->addMessage($id_chat, $id_user, 'assistant', $reply, $model);
        return array($id_chat, $reply);
    }

    /**
     * Llamada al proveedor LLM upstream. AQUÍ se enchufa el proveedor real.
     * De momento, según $_config['llm']['provider']:
     *   - 'stub'  -> respuesta de marcador (para desarrollo sin key).
     *   - otros   -> TODO: implementar el cliente HTTP del proveedor.
     *
     * @param array $history  [['role'=>..., 'content'=>...], ...]
     * @return string         contenido de la respuesta del asistente
     */
    protected function askUpstream($history)
    {
        $provider = $this->config['llm']['provider'] ?? 'stub';

        if ($provider === 'stub' || empty($this->config['llm']['api_key'])) {
            $last = '';
            foreach (array_reverse($history) as $m) {
                if ($m['role'] === 'user') { $last = $m['content']; break; }
            }
            return "🔧 (stub) Recibí: «" . $last . "».\n\n"
                 . "Conecta tu proveedor LLM en class/chat.php → askUpstream() "
                 . "usando la key de \$_config['llm'].";
        }

        // TODO: cliente real del proveedor (Claude/Gemini/...). Reenviar $history
        // al endpoint upstream con la api_key del servidor y devolver el texto.
        App::log('askUpstream: proveedor "' . $provider . '" sin implementar todavía.');
        return '(proveedor sin implementar)';
    }
}
