using WhatsAppService.Domain.Exceptions;
using WhatsAppService.Domain.SeedWork;

namespace WhatsAppService.Domain.AggregatesModel.AIAgentAggregate;

/// <summary>
/// EN: AIAgent aggregate root for managing LLM-powered chatbot configuration.
/// VI: AIAgent aggregate root để quản lý cấu hình chatbot dựa trên LLM.
/// </summary>
public class AIAgent : Entity, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private Guid _shopId;
    private string _agentName = null!;
    private AgentPersonality _personality = null!;
    private Guid? _knowledgeBaseId;
    private bool _isActive;
    private int? _maxPromptTokens;
    private int? _maxCompletionTokens;
    private decimal? _dailyBudgetUsd;
    private decimal? _monthlyBudgetUsd;
    private DateTime _createdAt;
    private DateTime? _updatedAt;

    /// <summary>
    /// EN: Shop ID that owns this agent.
    /// VI: Shop ID sở hữu agent này.
    /// </summary>
    public Guid ShopId => _shopId;

    /// <summary>
    /// EN: Agent display name.
    /// VI: Tên hiển thị của agent.
    /// </summary>
    public string AgentName => _agentName;

    /// <summary>
    /// EN: Agent personality configuration.
    /// VI: Cấu hình tính cách agent.
    /// </summary>
    public AgentPersonality Personality => _personality;

    /// <summary>
    /// EN: Optional knowledge base ID for RAG.
    /// VI: ID knowledge base tùy chọn cho RAG.
    /// </summary>
    public Guid? KnowledgeBaseId => _knowledgeBaseId;

    /// <summary>
    /// EN: Whether agent is active.
    /// VI: Agent có đang hoạt động không.
    /// </summary>
    public bool IsActive => _isActive;

    /// <summary>
    /// EN: Maximum prompt tokens (optional limit).
    /// VI: Số token prompt tối đa (giới hạn tùy chọn).
    /// </summary>
    public int? MaxPromptTokens => _maxPromptTokens;

    /// <summary>
    /// EN: Maximum completion tokens (optional limit).
    /// VI: Số token completion tối đa (giới hạn tùy chọn).
    /// </summary>
    public int? MaxCompletionTokens => _maxCompletionTokens;

    /// <summary>
    /// EN: Daily budget in USD.
    /// VI: Ngân sách hàng ngày tính bằng USD.
    /// </summary>
    public decimal? DailyBudgetUsd => _dailyBudgetUsd;

    /// <summary>
    /// EN: Monthly budget in USD.
    /// VI: Ngân sách hàng tháng tính bằng USD.
    /// </summary>
    public decimal? MonthlyBudgetUsd => _monthlyBudgetUsd;

    /// <summary>
    /// EN: Creation timestamp.
    /// VI: Thời gian tạo.
    /// </summary>
    public DateTime CreatedAt => _createdAt;

    /// <summary>
    /// EN: Last update timestamp.
    /// VI: Thời gian cập nhật cuối.
    /// </summary>
    public DateTime? UpdatedAt => _updatedAt;

    /// <summary>
    /// EN: Private constructor for EF Core.
    /// VI: Constructor private cho EF Core.
    /// </summary>
    protected AIAgent()
    {
    }

    /// <summary>
    /// EN: Create a new AI agent.
    /// VI: Tạo một AI agent mới.
    /// </summary>
    public AIAgent(Guid shopId, string agentName, AgentPersonality? personality = null) : this()
    {
        if (shopId == Guid.Empty)
            throw new AIAgentDomainException("Shop ID cannot be empty");
        
        if (string.IsNullOrWhiteSpace(agentName))
            throw new AIAgentDomainException("Agent name cannot be empty");

        Id = Guid.NewGuid();
        _shopId = shopId;
        _agentName = agentName;
        _personality = personality ?? AgentPersonality.CreateDefault();
        _isActive = false;
        _createdAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update agent name.
    /// VI: Cập nhật tên agent.
    /// </summary>
    public void UpdateName(string name)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new AIAgentDomainException("Agent name cannot be empty");

        _agentName = name;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update agent personality.
    /// VI: Cập nhật tính cách agent.
    /// </summary>
    public void UpdatePersonality(AgentPersonality personality)
    {
        _personality = personality ?? throw new ArgumentNullException(nameof(personality));
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Set knowledge base for RAG.
    /// VI: Đặt knowledge base cho RAG.
    /// </summary>
    public void SetKnowledgeBase(Guid? knowledgeBaseId)
    {
        _knowledgeBaseId = knowledgeBaseId;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Set token limits.
    /// VI: Đặt giới hạn token.
    /// </summary>
    public void SetTokenLimits(int? maxPromptTokens, int? maxCompletionTokens)
    {
        if (maxPromptTokens.HasValue && maxPromptTokens <= 0)
            throw new AIAgentDomainException("Max prompt tokens must be positive");
        
        if (maxCompletionTokens.HasValue && maxCompletionTokens <= 0)
            throw new AIAgentDomainException("Max completion tokens must be positive");

        _maxPromptTokens = maxPromptTokens;
        _maxCompletionTokens = maxCompletionTokens;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Set budget limits.
    /// VI: Đặt giới hạn ngân sách.
    /// </summary>
    public void SetBudget(decimal? dailyBudgetUsd, decimal? monthlyBudgetUsd)
    {
        if (dailyBudgetUsd.HasValue && dailyBudgetUsd <= 0)
            throw new AIAgentDomainException("Daily budget must be positive");
        
        if (monthlyBudgetUsd.HasValue && monthlyBudgetUsd <= 0)
            throw new AIAgentDomainException("Monthly budget must be positive");

        _dailyBudgetUsd = dailyBudgetUsd;
        _monthlyBudgetUsd = monthlyBudgetUsd;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Activate the AI agent.
    /// VI: Kích hoạt AI agent.
    /// </summary>
    public void Activate()
    {
        _isActive = true;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Deactivate the AI agent.
    /// VI: Hủy kích hoạt AI agent.
    /// </summary>
    public void Deactivate()
    {
        _isActive = false;
        _updatedAt = DateTime.UtcNow;
    }
}
