using MktXService.Domain.Events;
using MktXService.Domain.Exceptions;
using MktXService.Domain.SeedWork;

namespace MktXService.Domain.AggregatesModel.AIConversationSessionAggregate;

/// <summary>
/// EN: AIConversationSession aggregate root for maintaining AI conversation context and state.
/// VI: Aggregate root AIConversationSession để duy trì ngữ cảnh và trạng thái hội thoại AI.
/// </summary>
public class AIConversationSession : Entity, IAggregateRoot
{
    private const int MaxContextItems = 10;
    private const double EscalationThreshold = 0.6;

    private Guid _conversationId;
    private List<ContextItem> _context = new();
    private string? _currentIntent;
    private Dictionary<string, object> _slots = new();
    private bool _isActive;
    private DateTime? _lastActivityAt;
    private DateTime _createdAt;

    public Guid ConversationId => _conversationId;
    public IReadOnlyList<ContextItem> Context => _context.AsReadOnly();
    public string? CurrentIntent => _currentIntent;
    public IReadOnlyDictionary<string, object> Slots => _slots;
    public bool IsActive => _isActive;
    public DateTime? LastActivityAt => _lastActivityAt;
    public DateTime CreatedAt => _createdAt;

    protected AIConversationSession() { }

    public AIConversationSession(Guid conversationId) : this()
    {
        if (conversationId == Guid.Empty)
            throw new AIConversationSessionDomainException("Conversation ID cannot be empty");

        Id = Guid.NewGuid();
        _conversationId = conversationId;
        _isActive = true;
        _lastActivityAt = DateTime.UtcNow;
        _createdAt = DateTime.UtcNow;
    }

    public void AddContext(string role, string content)
    {
        var item = new ContextItem(role, content, DateTime.UtcNow);
        _context.Add(item);

        // Keep only last N context items
        if (_context.Count > MaxContextItems)
        {
            _context = _context.TakeLast(MaxContextItems).ToList();
        }

        _lastActivityAt = DateTime.UtcNow;
    }

    public void ClearContext()
    {
        _context.Clear();
        _currentIntent = null;
        _slots.Clear();
        _lastActivityAt = DateTime.UtcNow;
    }

    public void SetIntent(string intent, double confidence)
    {
        _currentIntent = intent;
        _lastActivityAt = DateTime.UtcNow;

        // Auto-escalate if confidence is too low
        if (confidence < EscalationThreshold)
        {
            AddDomainEvent(new AIEscalationRequestedDomainEvent(Id, $"Low confidence: {confidence:P}"));
        }
        else
        {
            AddDomainEvent(new IntentDetectedDomainEvent(Id, intent, confidence));
        }
    }

    public void SetSlot(string key, object value)
    {
        if (string.IsNullOrWhiteSpace(key))
            throw new AIConversationSessionDomainException("Slot key cannot be empty");

        _slots[key] = value;
        _lastActivityAt = DateTime.UtcNow;
    }

    public void Deactivate()
    {
        _isActive = false;
    }

    public void Reactivate()
    {
        _isActive = true;
        _lastActivityAt = DateTime.UtcNow;
    }

    public bool IsExpired(TimeSpan timeout)
    {
        if (!_lastActivityAt.HasValue) return true;
        return DateTime.UtcNow - _lastActivityAt.Value > timeout;
    }
}

public record ContextItem(string Role, string Content, DateTime Timestamp);
