using ManagerService.Data;
using System.Collections.Generic;
namespace ManagerService.DTOs
{
public class AiChatRequest
{
public string Message { get; set; }
public string InstanceId { get; set; }
public AppType AppType { get; set; }
public string ConfigurationId { get; set; } // null = scope instance, fourni = scope configuration
public string Language { get; set; }
///
/// GUID généré par le client, stable sur une session de conversation.
/// History étant reconstruit côté client à chaque appel, c'est le seul moyen
/// de relier deux questions d'un même visiteur côté serveur.
/// Optionnel : un appel sans ConversationId reste valide, la ligne journalisée est isolée.
///
public string ConversationId { get; set; }
public List History { get; set; } = new();
///
/// true = interaction vocale (lunettes, assistant vocal).
/// Le backend adapte le prompt : pas de markdown, pas de navigation,
/// dates en toutes lettres, réponses courtes audio-friendly.
///
public bool IsVoice { get; set; } = false;
///
/// true = le tour a été déclenché par le système, pas demandé par le visiteur —
/// c'est le cas du mode proactif, où l'approche d'un point d'intérêt fait parler
/// le guide tout seul.
///
/// ⚠️ Ces tours ne sont **pas journalisés** dans VisitorQuestion : leur
/// « question » est une consigne que le système s'est écrite à lui-même
/// (« Tu es un guide audio de musée. Le visiteur vient d'entrer dans la zone X… »),
/// et l'onglet Guide IA existe pour montrer ce que les **humains** demandent.
/// Leurs jetons, eux, restent comptés : ils sont réellement consommés.
///
public bool IsAutoTriggered { get; set; } = false;
}
public class AiChatMessage
{
public string Role { get; set; } // "user" | "assistant"
public string Content { get; set; }
}
public class AiCardDTO
{
public string Title { get; set; }
public string Subtitle { get; set; }
public string? Icon { get; set; }
}
public class NavigationActionDTO
{
public string SectionId { get; set; }
public string SectionTitle { get; set; }
public string SectionType { get; set; }
public string? ImageUrl { get; set; }
}
public class AiChatResponse
{
public string Reply { get; set; }
public List? Cards { get; set; }
public NavigationActionDTO? Navigation { get; set; }
///
/// false = le LLM ne s'attend pas à une réponse du visiteur (info pure, hors-sujet, politesse, beacon).
/// Le front peut désactiver l'écoute automatique après le TTS.
///
public bool ExpectsReply { get; set; } = true;
public long TokensUsed { get; set; }
///
/// Contenus sur lesquels la réponse s'appuie, relevés côté serveur à chaque appel de
/// SearchKnowledge. Ils ne passent pas par le modèle : la règle « ne mentionne jamais
/// les identifiants techniques » lui interdit précisément de les recopier.
/// Destinés au client, pas au visiteur — c'est ce qui rend une réponse vérifiable
/// quand un client conteste ce que dit son guide.
///
public List? Sources { get; set; }
}
public class AiSourceDTO
{
public string ContentId { get; set; }
public string ContentType { get; set; }
/// Null hors document paginé.
public int? PageNumber { get; set; }
}
public class AiTranslateRequest
{
public string Text { get; set; }
public string SourceLang { get; set; }
public List TargetLangs { get; set; } = new();
}
public class AiTranslateResponse
{
public Dictionary Translations { get; set; } = new();
public long TokensUsed { get; set; }
}
}