<?php
namespace Infrastructure\Persistence;
use Domain\Repository\ChatSessionRepositoryInterface;
use Infrastructure\Config\DatabaseFactory;
/**
* Repository for Chat Session operations.
*/
class ChatSessionRepository implements ChatSessionRepositoryInterface
{
private \PDO $pdo;
public function __construct(?\PDO $pdo = null)
{
$this->pdo = $pdo ?? DatabaseFactory::content();
}
public function findByUuid(string $uuid): ?array
{
$stmt = $this->pdo->prepare('SELECT * FROM chat_sessions WHERE uuid = ?');
$stmt->execute([$uuid]);
$result = $stmt->fetch(\PDO::FETCH_ASSOC);
return $result !== false ? $result : null;
}
public function findAll(int $limit = 50): array
{
$stmt = $this->pdo->query(
'SELECT s.*,
(SELECT COUNT(*) FROM chat_messages WHERE session_id = s.id) as message_count,
(SELECT COALESCE(SUM(tokens_input), 0) FROM chat_messages WHERE session_id = s.id) as total_input_tokens,
(SELECT COALESCE(SUM(tokens_output), 0) FROM chat_messages WHERE session_id = s.id) as total_output_tokens,
(SELECT COALESCE(SUM(end_microtime - start_microtime), 0) FROM chat_messages WHERE session_id = s.id AND start_microtime IS NOT NULL) as total_duration,
(SELECT model FROM chat_messages WHERE session_id = s.id AND role = "assistant" ORDER BY id DESC LIMIT 1) as last_model
FROM chat_sessions s
ORDER BY s.last_activity DESC
LIMIT ' . $limit
);
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
public function create(string $uuid, string $model, string $collections, int $contextLimit): int
{
$stmt = $this->pdo->prepare(
'INSERT INTO chat_sessions (uuid, model, collections, context_limit) VALUES (?, ?, ?, ?)'
);
$stmt->execute([$uuid, $model, $collections, $contextLimit]);
return (int) $this->pdo->lastInsertId();
}
public function updateTitle(int $sessionId, string $title): void
{
$stmt = $this->pdo->prepare('UPDATE chat_sessions SET title = ? WHERE id = ?');
$stmt->execute([$title, $sessionId]);
}
public function updateSettings(
int $sessionId,
string $model,
array $collections,
int $contextLimit,
?int $authorProfileId,
float $temperature,
int $maxTokens
): void {
$collectionsJson = json_encode($collections);
$stmt = $this->pdo->prepare(
'UPDATE chat_sessions SET model = ?, collections = ?, context_limit = ?, author_profile_id = ?, temperature = ?, max_tokens = ? WHERE id = ?'
);
$stmt->execute([
$model,
$collectionsJson,
$contextLimit,
$authorProfileId > 0 ? $authorProfileId : null,
$temperature,
$maxTokens,
$sessionId,
]);
}
public function updateSystemPrompt(int $sessionId, ?string $systemPrompt): void
{
$stmt = $this->pdo->prepare('UPDATE chat_sessions SET system_prompt = ? WHERE id = ?');
$stmt->execute([$systemPrompt !== '' ? $systemPrompt : null, $sessionId]);
}
public function delete(int $sessionId): void
{
$stmt = $this->pdo->prepare('DELETE FROM chat_sessions WHERE id = ?');
$stmt->execute([$sessionId]);
}
public function touch(int $sessionId): void
{
$stmt = $this->pdo->prepare('UPDATE chat_sessions SET updated_at = NOW() WHERE id = ?');
$stmt->execute([$sessionId]);
}
public function generateUuid(): string
{
$data = random_bytes(16);
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
}