using MediatR;
using IamService.Domain.AggregatesModel.ComplianceAggregate;

namespace IamService.API.Application.Queries.Compliance;

public record GetComplianceReportsQuery(int? ReportTypeId = null, int Take = 20) : IRequest<IEnumerable<ComplianceReportDto>>;
public record GetComplianceReportByIdQuery(Guid Id) : IRequest<ComplianceReportDetailDto?>;
public record GetUnresolvedViolationsQuery() : IRequest<IEnumerable<ViolationDto>>;

public record ComplianceReportDto(Guid Id, string Name, string ReportType, string Status, DateTime CreatedAt, double CompliancePercentage);
public record ComplianceReportDetailDto(Guid Id, string Name, string ReportType, string Status, DateTime CreatedAt, DateTime? CompletedAt, 
    int TotalChecks, int PassedChecks, int FailedChecks, double CompliancePercentage, string? Summary, IEnumerable<ViolationDto> Violations);
public record ViolationDto(Guid Id, string Rule, string Severity, string Description, string? Remediation, bool Resolved);

public class GetComplianceReportsQueryHandler : IRequestHandler<GetComplianceReportsQuery, IEnumerable<ComplianceReportDto>>
{
    private readonly IComplianceReportRepository _repository;
    public GetComplianceReportsQueryHandler(IComplianceReportRepository repository) => _repository = repository;

    public async Task<IEnumerable<ComplianceReportDto>> Handle(GetComplianceReportsQuery request, CancellationToken ct)
    {
        var reports = request.ReportTypeId.HasValue
            ? await _repository.GetByTypeAsync(request.ReportTypeId.Value, request.Take, ct)
            : await _repository.GetRecentAsync(request.Take, ct);
        return reports.Select(r => new ComplianceReportDto(r.Id, r.Name, r.ReportType.Name, r.Status.Name, r.CreatedAt, r.CompliancePercentage));
    }
}

public class GetComplianceReportByIdQueryHandler : IRequestHandler<GetComplianceReportByIdQuery, ComplianceReportDetailDto?>
{
    private readonly IComplianceReportRepository _repository;
    public GetComplianceReportByIdQueryHandler(IComplianceReportRepository repository) => _repository = repository;

    public async Task<ComplianceReportDetailDto?> Handle(GetComplianceReportByIdQuery request, CancellationToken ct)
    {
        var r = await _repository.GetByIdWithViolationsAsync(request.Id, ct);
        if (r == null) return null;
        var violations = r.Violations.Select(v => new ViolationDto(v.Id, v.Rule, v.Severity.Name, v.Description, v.Remediation, v.Resolved));
        return new ComplianceReportDetailDto(r.Id, r.Name, r.ReportType.Name, r.Status.Name, r.CreatedAt, r.CompletedAt, 
            r.TotalChecks, r.PassedChecks, r.FailedChecks, r.CompliancePercentage, r.Summary, violations);
    }
}

public class GetUnresolvedViolationsQueryHandler : IRequestHandler<GetUnresolvedViolationsQuery, IEnumerable<ViolationDto>>
{
    private readonly IComplianceReportRepository _repository;
    public GetUnresolvedViolationsQueryHandler(IComplianceReportRepository repository) => _repository = repository;

    public async Task<IEnumerable<ViolationDto>> Handle(GetUnresolvedViolationsQuery request, CancellationToken ct)
    {
        var violations = await _repository.GetUnresolvedViolationsAsync(ct);
        return violations.Select(v => new ViolationDto(v.Id, v.Rule, v.Severity.Name, v.Description, v.Remediation, v.Resolved));
    }
}
