using IamService.Domain.SeedWork;

namespace IamService.Domain.AggregatesModel.AuditAggregate;

/// <summary>
/// EN: Audit log aggregate root for system-wide event logging.
/// VI: Aggregate root audit log cho ghi nhận sự kiện toàn hệ thống.
/// </summary>
public class AuditLog : Entity, IAggregateRoot
{
    private AuditEventType _eventType = null!;
    private Guid? _actorId;
    private string? _actorEmail;
    private string _resourceType = null!;
    private Guid? _resourceId;
    private string? _action;
    private string? _details;
    private string? _ipAddress;
    private string? _userAgent;
    private bool _success;
    private DateTime _timestamp;

    #region Properties
    public AuditEventType EventType => _eventType;
    public Guid? ActorId => _actorId;
    public string? ActorEmail => _actorEmail;
    public string ResourceType => _resourceType;
    public Guid? ResourceId => _resourceId;
    public string? Action => _action;
    public string? Details => _details;
    public string? IpAddress => _ipAddress;
    public string? UserAgent => _userAgent;
    public bool Success => _success;
    public DateTime Timestamp => _timestamp;
    #endregion

    protected AuditLog() { }

    private AuditLog(
        AuditEventType eventType,
        Guid? actorId,
        string? actorEmail,
        string resourceType,
        Guid? resourceId,
        string? action,
        string? details,
        string? ipAddress,
        string? userAgent,
        bool success)
    {
        Id = Guid.NewGuid();
        _eventType = eventType;
        _actorId = actorId;
        _actorEmail = actorEmail;
        _resourceType = resourceType;
        _resourceId = resourceId;
        _action = action;
        _details = details;
        _ipAddress = ipAddress;
        _userAgent = userAgent;
        _success = success;
        _timestamp = DateTime.UtcNow;
    }

    public static AuditLog Create(
        AuditEventType eventType,
        string resourceType,
        Guid? actorId = null,
        string? actorEmail = null,
        Guid? resourceId = null,
        string? action = null,
        string? details = null,
        string? ipAddress = null,
        string? userAgent = null,
        bool success = true)
    {
        if (string.IsNullOrWhiteSpace(resourceType))
            throw new ArgumentException("Resource type is required", nameof(resourceType));

        return new AuditLog(eventType, actorId, actorEmail, resourceType, resourceId, action, details, ipAddress, userAgent, success);
    }

    /// <summary>
    /// EN: Create login event.
    /// VI: Tạo event đăng nhập.
    /// </summary>
    public static AuditLog LoginEvent(Guid userId, string email, string? ipAddress, string? userAgent, bool success = true)
        => Create(
            success ? AuditEventType.Login : AuditEventType.LoginFailed,
            "User", userId, email, userId, 
            success ? "User logged in" : "Login attempt failed",
            null, ipAddress, userAgent, success);

    /// <summary>
    /// EN: Create access granted event.
    /// VI: Tạo event cấp quyền truy cập.
    /// </summary>
    public static AuditLog AccessGrantedEvent(Guid actorId, string actorEmail, string resourceType, Guid resourceId, string permission)
        => Create(AuditEventType.AccessGranted, resourceType, actorId, actorEmail, resourceId, 
            $"Access granted: {permission}", null, null, null);
}
