using System.Text.RegularExpressions;
using MktXService.Domain.Exceptions;
using MktXService.Domain.SeedWork;

namespace MktXService.Domain.AggregatesModel.TemplateAggregate;

/// <summary>
/// EN: Template aggregate root for reusable message templates with variable substitution.
/// VI: Aggregate root Template cho mẫu tin nhắn có thể tái sử dụng với thay thế biến.
/// </summary>
public partial class Template : Entity, IAggregateRoot
{
    private const int MaxContentLength = 10000; // Twitter DM limit
    private static readonly Regex VariablePattern = VariableRegex();

    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private Guid _merchantId;
    private string _name = null!;
    private string _type = null!;
    private string _content = null!;
    private List<string> _variables = new();
    private DateTime _createdAt;
    private DateTime? _updatedAt;

    /// <summary>
    /// EN: Merchant ID who owns this template.
    /// VI: ID merchant sở hữu template này.
    /// </summary>
    public Guid MerchantId => _merchantId;

    /// <summary>
    /// EN: Template name.
    /// VI: Tên template.
    /// </summary>
    public string Name => _name;

    /// <summary>
    /// EN: Template type (text/quick_reply/card).
    /// VI: Loại template (text/quick_reply/card).
    /// </summary>
    public string Type => _type;

    /// <summary>
    /// EN: Template content with {{variable}} placeholders.
    /// VI: Nội dung template với các placeholder {{variable}}.
    /// </summary>
    public string Content => _content;

    /// <summary>
    /// EN: List of variable names in this template.
    /// VI: Danh sách tên biến trong template này.
    /// </summary>
    public IReadOnlyList<string> Variables => _variables.AsReadOnly();

    /// <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 Template()
    {
    }

    /// <summary>
    /// EN: Create a new message template.
    /// VI: Tạo một template tin nhắn mới.
    /// </summary>
    public Template(Guid merchantId, string name, string type, string content) : this()
    {
        if (merchantId == Guid.Empty)
            throw new TemplateDomainException("Merchant ID cannot be empty");
        if (string.IsNullOrWhiteSpace(name))
            throw new TemplateDomainException("Template name cannot be empty");
        if (string.IsNullOrWhiteSpace(type))
            throw new TemplateDomainException("Template type cannot be empty");
        if (string.IsNullOrWhiteSpace(content))
            throw new TemplateDomainException("Template content cannot be empty");
        if (content.Length > MaxContentLength)
            throw new TemplateDomainException($"Template content exceeds maximum length of {MaxContentLength} characters");

        Id = Guid.NewGuid();
        _merchantId = merchantId;
        _name = name;
        _type = type;
        _content = content;
        _variables = ExtractVariables(content);
        _createdAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update template name and content.
    /// VI: Cập nhật tên và nội dung template.
    /// </summary>
    public void Update(string name, string content)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new TemplateDomainException("Template name cannot be empty");
        if (string.IsNullOrWhiteSpace(content))
            throw new TemplateDomainException("Template content cannot be empty");
        if (content.Length > MaxContentLength)
            throw new TemplateDomainException($"Template content exceeds maximum length of {MaxContentLength} characters");

        _name = name;
        _content = content;
        _variables = ExtractVariables(content);
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Render the template with provided variable values.
    /// VI: Render template với các giá trị biến được cung cấp.
    /// </summary>
    public string Render(Dictionary<string, object> values)
    {
        if (values == null)
            values = new Dictionary<string, object>();

        var result = _content;

        foreach (var variable in _variables)
        {
            var placeholder = $"{{{{{variable}}}}}";
            var value = values.TryGetValue(variable, out var v) ? v?.ToString() ?? "" : "";
            result = result.Replace(placeholder, value);
        }

        return result;
    }

    /// <summary>
    /// EN: Validate that all required variables are provided.
    /// VI: Xác thực rằng tất cả các biến bắt buộc đã được cung cấp.
    /// </summary>
    public bool ValidateVariables(Dictionary<string, object> values)
    {
        if (values == null)
            return _variables.Count == 0;

        var missingVariables = _variables.Where(v => !values.ContainsKey(v)).ToList();
        return missingVariables.Count == 0;
    }

    /// <summary>
    /// EN: Get list of missing variables.
    /// VI: Lấy danh sách các biến còn thiếu.
    /// </summary>
    public List<string> GetMissingVariables(Dictionary<string, object> values)
    {
        if (values == null)
            return _variables.ToList();

        return _variables.Where(v => !values.ContainsKey(v)).ToList();
    }

    /// <summary>
    /// EN: Extract variable names from content.
    /// VI: Trích xuất tên biến từ nội dung.
    /// </summary>
    private static List<string> ExtractVariables(string content)
    {
        var matches = VariablePattern.Matches(content);
        return matches.Select(m => m.Groups[1].Value).Distinct().ToList();
    }

    [GeneratedRegex(@"\{\{(\w+)\}\}")]
    private static partial Regex VariableRegex();
}
