using IamService.Domain.AggregatesModel.GroupAggregate;
using IamService.Domain.Events;
using IamService.Domain.SeedWork;

namespace IamService.Domain.AggregatesModel.OrganizationAggregate;

/// <summary>
/// EN: Organization aggregate root for multi-tenant support.
/// VI: Aggregate root tổ chức cho hỗ trợ multi-tenant.
/// </summary>
public class Organization : Entity, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private string _name = null!;
    private string _slug = null!;
    private string? _description;
    private Guid? _parentOrganizationId;
    private OrganizationStatus _status = null!;
    private OrganizationSettings _settings = null!;
    private DateTime _createdAt;
    private DateTime? _updatedAt;


    /// <summary>
    /// EN: Organization name.
    /// VI: Tên tổ chức.
    /// </summary>
    public string Name => _name;

    /// <summary>
    /// EN: URL-friendly unique identifier.
    /// VI: Định danh duy nhất thân thiện với URL.
    /// </summary>
    public string Slug => _slug;

    /// <summary>
    /// EN: Organization description.
    /// VI: Mô tả tổ chức.
    /// </summary>
    public string? Description => _description;

    /// <summary>
    /// EN: Parent organization ID for hierarchy.
    /// VI: ID tổ chức cha cho phân cấp.
    /// </summary>
    public Guid? ParentOrganizationId => _parentOrganizationId;

    /// <summary>
    /// EN: Current status of the organization.
    /// VI: Trạng thái hiện tại của tổ chức.
    /// </summary>
    public OrganizationStatus Status => _status;

    /// <summary>
    /// EN: Status ID for EF Core mapping.
    /// VI: ID trạng thái cho EF Core mapping.
    /// </summary>
    public int StatusId { get; private set; }

    /// <summary>
    /// EN: Organization settings.
    /// VI: Cấu hình tổ chức.
    /// </summary>
    public OrganizationSettings Settings => _settings;

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

    /// <summary>
    /// EN: Create a new organization.
    /// VI: Tạo tổ chức mới.
    /// </summary>
    /// <param name="name">Organization name / Tên tổ chức</param>
    /// <param name="slug">URL-friendly slug / Slug thân thiện URL</param>
    /// <param name="description">Optional description / Mô tả tùy chọn</param>
    /// <param name="parentOrganizationId">Optional parent ID / ID cha tùy chọn</param>
    /// <param name="settings">Optional settings / Cấu hình tùy chọn</param>
    public Organization(
        string name,
        string slug,
        string? description = null,
        Guid? parentOrganizationId = null,
        OrganizationSettings? settings = null) : this()
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new ArgumentException("Organization name cannot be empty", nameof(name));
        if (string.IsNullOrWhiteSpace(slug))
            throw new ArgumentException("Organization slug cannot be empty", nameof(slug));
        if (!IsValidSlug(slug))
            throw new ArgumentException("Slug must contain only lowercase letters, numbers, and hyphens", nameof(slug));

        Id = Guid.NewGuid();
        _name = name.Trim();
        _slug = slug.ToLowerInvariant().Trim();
        _description = description?.Trim();
        _parentOrganizationId = parentOrganizationId;
        _status = OrganizationStatus.Active;
        StatusId = OrganizationStatus.Active.Id;
        _settings = settings ?? OrganizationSettings.Default;
        _createdAt = DateTime.UtcNow;

        AddDomainEvent(new OrganizationCreatedEvent(Id, _name, _slug));
    }

    /// <summary>
    /// EN: Factory method to create organization.
    /// VI: Factory method để tạo tổ chức.
    /// </summary>
    public static Organization Create(
        string name,
        string slug,
        string? description = null,
        Guid? parentOrganizationId = null,
        OrganizationSettings? settings = null)
    {
        return new Organization(name, slug, description, parentOrganizationId, settings);
    }

    /// <summary>
    /// EN: Update organization information.
    /// VI: Cập nhật thông tin tổ chức.
    /// </summary>
    public void UpdateInfo(string name, string? description)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new ArgumentException("Organization name cannot be empty", nameof(name));

        _name = name.Trim();
        _description = description?.Trim();
        _updatedAt = DateTime.UtcNow;

        AddDomainEvent(new OrganizationUpdatedEvent(Id, _name));
    }

    /// <summary>
    /// EN: Update organization slug.
    /// VI: Cập nhật slug tổ chức.
    /// </summary>
    public void UpdateSlug(string slug)
    {
        if (string.IsNullOrWhiteSpace(slug))
            throw new ArgumentException("Organization slug cannot be empty", nameof(slug));
        if (!IsValidSlug(slug))
            throw new ArgumentException("Slug must contain only lowercase letters, numbers, and hyphens", nameof(slug));

        _slug = slug.ToLowerInvariant().Trim();
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Set parent organization for hierarchy.
    /// VI: Đặt tổ chức cha cho phân cấp.
    /// </summary>
    public void SetParent(Guid? parentOrganizationId)
    {
        if (parentOrganizationId == Id)
            throw new InvalidOperationException("Organization cannot be its own parent");

        _parentOrganizationId = parentOrganizationId;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Update organization settings.
    /// VI: Cập nhật cấu hình tổ chức.
    /// </summary>
    public void UpdateSettings(OrganizationSettings settings)
    {
        _settings = settings ?? throw new ArgumentNullException(nameof(settings));
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Activate the organization.
    /// VI: Kích hoạt tổ chức.
    /// </summary>
    public void Activate()
    {
        if (_status == OrganizationStatus.Archived)
            throw new InvalidOperationException("Cannot activate an archived organization");

        _status = OrganizationStatus.Active;
        StatusId = OrganizationStatus.Active.Id;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Suspend the organization.
    /// VI: Tạm ngưng tổ chức.
    /// </summary>
    public void Suspend()
    {
        if (_status == OrganizationStatus.Archived)
            throw new InvalidOperationException("Cannot suspend an archived organization");

        _status = OrganizationStatus.Suspended;
        StatusId = OrganizationStatus.Suspended.Id;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Archive the organization (soft delete).
    /// VI: Lưu trữ tổ chức (xóa mềm).
    /// </summary>
    public void Archive()
    {
        _status = OrganizationStatus.Archived;
        StatusId = OrganizationStatus.Archived.Id;
        _updatedAt = DateTime.UtcNow;
    }


    /// <summary>
    /// EN: Validate slug format.
    /// VI: Kiểm tra định dạng slug.
    /// </summary>
    private static bool IsValidSlug(string slug)
    {
        return System.Text.RegularExpressions.Regex.IsMatch(
            slug,
            @"^[a-z0-9]+(?:-[a-z0-9]+)*$"
        );
    }
}
