using IamService.Domain.Events;
using IamService.Domain.SeedWork;

namespace IamService.Domain.AggregatesModel.ComplianceAggregate;

/// <summary>
/// EN: Compliance report aggregate root.
/// VI: Aggregate root báo cáo tuân thủ.
/// </summary>
public class ComplianceReport : Entity, IAggregateRoot
{
    private string _name = null!;
    private ComplianceReportType _reportType = null!;
    private ComplianceReportStatus _status = null!;
    private Guid _generatedByUserId;
    private DateTime _createdAt;
    private DateTime? _completedAt;
    private string? _summary;
    private int _totalChecks;
    private int _passedChecks;
    private int _failedChecks;

    private readonly List<ComplianceViolation> _violations = [];

    #region Properties
    public string Name => _name;
    public ComplianceReportType ReportType => _reportType;
    public ComplianceReportStatus Status => _status;
    public Guid GeneratedByUserId => _generatedByUserId;
    public DateTime CreatedAt => _createdAt;
    public DateTime? CompletedAt => _completedAt;
    public string? Summary => _summary;
    public int TotalChecks => _totalChecks;
    public int PassedChecks => _passedChecks;
    public int FailedChecks => _failedChecks;
    public IReadOnlyCollection<ComplianceViolation> Violations => _violations.AsReadOnly();
    public double CompliancePercentage => _totalChecks > 0 ? (double)_passedChecks / _totalChecks * 100 : 0;
    #endregion

    protected ComplianceReport() { }

    private ComplianceReport(string name, ComplianceReportType reportType, Guid generatedByUserId)
    {
        Id = Guid.NewGuid();
        _name = name;
        _reportType = reportType;
        _status = ComplianceReportStatus.Pending;
        _generatedByUserId = generatedByUserId;
        _createdAt = DateTime.UtcNow;

        AddDomainEvent(new ComplianceReportCreatedEvent(Id, name, reportType.Name));
    }

    public static ComplianceReport Create(string name, ComplianceReportType reportType, Guid generatedByUserId)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new ArgumentException("Name is required", nameof(name));
        return new ComplianceReport(name, reportType, generatedByUserId);
    }

    public void StartGenerating()
    {
        if (_status != ComplianceReportStatus.Pending)
            throw new InvalidOperationException("Only pending reports can be started");
        _status = ComplianceReportStatus.Generating;
    }

    public void SetResults(int totalChecks, int passedChecks, string? summary = null)
    {
        _totalChecks = totalChecks;
        _passedChecks = passedChecks;
        _failedChecks = totalChecks - passedChecks;
        _summary = summary;
    }

    public void AddViolation(string rule, ViolationSeverity severity, string description, string? remediation = null)
    {
        var violation = new ComplianceViolation(Id, rule, severity, description, remediation);
        _violations.Add(violation);
    }

    public void Complete()
    {
        _status = ComplianceReportStatus.Completed;
        _completedAt = DateTime.UtcNow;
        AddDomainEvent(new ComplianceReportCompletedEvent(Id, _passedChecks, _failedChecks, _violations.Count));
    }

    public void Fail(string? reason = null)
    {
        _status = ComplianceReportStatus.Failed;
        _summary = reason ?? "Report generation failed";
    }
}
