using System.Text.Json;
using WhatsAppService.Domain.Exceptions;
using WhatsAppService.Domain.SeedWork;

namespace WhatsAppService.Domain.AggregatesModel.AutomationFlowAggregate;

/// <summary>
/// EN: AutomationFlow aggregate root for managing rule-based chatbot flows.
/// VI: AutomationFlow aggregate root để quản lý các flows chatbot dựa trên quy tắc.
/// </summary>
public class AutomationFlow : Entity, IAggregateRoot
{
    /// <summary>
    /// EN: Maximum steps allowed per flow.
    /// VI: Số bước tối đa được phép trong mỗi flow.
    /// </summary>
    public const int MaxSteps = 20;

    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private Guid _shopId;
    private string _flowName = null!;
    private TriggerType _triggerType = null!;
    private string _triggerConfig = null!;
    private bool _isActive;
    private int _priority = 50;
    private int _executionCount;
    private readonly List<FlowStep> _steps = new();
    private DateTime _createdAt;
    private DateTime? _updatedAt;

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

    /// <summary>
    /// EN: Flow name.
    /// VI: Tên flow.
    /// </summary>
    public string FlowName => _flowName;

    /// <summary>
    /// EN: Trigger type.
    /// VI: Loại trigger.
    /// </summary>
    public TriggerType TriggerType => _triggerType;

    /// <summary>
    /// EN: Trigger type ID for EF Core mapping.
    /// VI: ID loại trigger cho EF Core mapping.
    /// </summary>
    public int TriggerTypeId { get; private set; }

    /// <summary>
    /// EN: Trigger configuration as JSON.
    /// VI: Cấu hình trigger dạng JSON.
    /// </summary>
    public string TriggerConfig => _triggerConfig;

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

    /// <summary>
    /// EN: Flow priority (higher = higher priority).
    /// VI: Độ ưu tiên flow (cao hơn = ưu tiên hơn).
    /// </summary>
    public int Priority => _priority;

    /// <summary>
    /// EN: Number of times this flow has been executed.
    /// VI: Số lần flow này được thực thi.
    /// </summary>
    public int ExecutionCount => _executionCount;

    /// <summary>
    /// EN: Flow steps (read-only).
    /// VI: Các bước flow (chỉ đọc).
    /// </summary>
    public IReadOnlyCollection<FlowStep> Steps => _steps.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 AutomationFlow()
    {
    }

    /// <summary>
    /// EN: Create a new automation flow.
    /// VI: Tạo một automation flow mới.
    /// </summary>
    public AutomationFlow(Guid shopId, string flowName, TriggerType triggerType, object triggerConfig) : this()
    {
        if (shopId == Guid.Empty)
            throw new AutomationFlowDomainException("Shop ID cannot be empty");
        
        if (string.IsNullOrWhiteSpace(flowName))
            throw new AutomationFlowDomainException("Flow name cannot be empty");

        Id = Guid.NewGuid();
        _shopId = shopId;
        _flowName = flowName;
        _triggerType = triggerType ?? throw new ArgumentNullException(nameof(triggerType));
        TriggerTypeId = triggerType.Id;
        _triggerConfig = JsonSerializer.Serialize(triggerConfig);
        _isActive = false;
        _createdAt = DateTime.UtcNow;
    }

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

        _flowName = name;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update trigger configuration.
    /// VI: Cập nhật cấu hình trigger.
    /// </summary>
    public void UpdateTrigger(TriggerType triggerType, object triggerConfig)
    {
        _triggerType = triggerType ?? throw new ArgumentNullException(nameof(triggerType));
        TriggerTypeId = triggerType.Id;
        _triggerConfig = JsonSerializer.Serialize(triggerConfig);
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Set flow priority.
    /// VI: Đặt độ ưu tiên flow.
    /// </summary>
    public void SetPriority(int priority)
    {
        if (priority < 0 || priority > 100)
            throw new AutomationFlowDomainException("Priority must be between 0 and 100");

        _priority = priority;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Add a step to the flow.
    /// VI: Thêm một bước vào flow.
    /// </summary>
    public FlowStep AddStep(string action, object actionConfig, object? conditions = null, object? nextStepMapping = null)
    {
        if (_steps.Count >= MaxSteps)
            throw new AutomationFlowDomainException($"Maximum of {MaxSteps} steps allowed per flow");

        var order = _steps.Count + 1;
        var step = new FlowStep(Id, order, action, actionConfig, conditions, nextStepMapping);
        _steps.Add(step);
        _updatedAt = DateTime.UtcNow;

        return step;
    }

    /// <summary>
    /// EN: Remove a step from the flow.
    /// VI: Xóa một bước khỏi flow.
    /// </summary>
    public void RemoveStep(Guid stepId)
    {
        var step = _steps.FirstOrDefault(s => s.Id == stepId);
        if (step != null)
        {
            _steps.Remove(step);
            // EN: Re-order remaining steps
            // VI: Sắp xếp lại các bước còn lại
            for (int i = 0; i < _steps.Count; i++)
            {
                _steps[i].SetOrder(i + 1);
            }
            _updatedAt = DateTime.UtcNow;
        }
    }

    /// <summary>
    /// EN: Validate flow structure (check for cycles, required fields).
    /// VI: Kiểm tra cấu trúc flow (kiểm tra vòng lặp, các trường bắt buộc).
    /// </summary>
    public bool ValidateFlow()
    {
        if (_steps.Count == 0)
            return false;

        // EN: Basic validation - steps exist and are ordered
        // VI: Kiểm tra cơ bản - các bước tồn tại và được sắp xếp
        var orders = _steps.Select(s => s.Order).OrderBy(o => o).ToList();
        for (int i = 0; i < orders.Count; i++)
        {
            if (orders[i] != i + 1)
                return false;
        }

        return true;
    }

    /// <summary>
    /// EN: Activate the flow.
    /// VI: Kích hoạt flow.
    /// </summary>
    public void Activate()
    {
        if (!ValidateFlow())
            throw new AutomationFlowDomainException("Cannot activate invalid flow. Ensure flow has valid steps.");

        _isActive = true;
        _updatedAt = DateTime.UtcNow;
    }

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

    /// <summary>
    /// EN: Increment execution count.
    /// VI: Tăng số lần thực thi.
    /// </summary>
    public void IncrementExecutionCount()
    {
        _executionCount++;
    }
}
