using System;
using System.Collections.Immutable;
using System.Linq;

namespace StellaOps.Policy;

public sealed record PolicyDiagnosticsReport(
    string Version,
    int RuleCount,
    int ErrorCount,
    int WarningCount,
    DateTimeOffset GeneratedAt,
    ImmutableArray<PolicyIssue> Issues,
    ImmutableArray<string> Recommendations);

public static class PolicyDiagnostics
{
    public static PolicyDiagnosticsReport Create(PolicyBindingResult bindingResult, TimeProvider? timeProvider = null)
    {
        if (bindingResult is null)
        {
            throw new ArgumentNullException(nameof(bindingResult));
        }

        var time = (timeProvider ?? TimeProvider.System).GetUtcNow();
        var errorCount = bindingResult.Issues.Count(static issue => issue.Severity == PolicyIssueSeverity.Error);
        var warningCount = bindingResult.Issues.Count(static issue => issue.Severity == PolicyIssueSeverity.Warning);

        var recommendations = BuildRecommendations(bindingResult.Document, errorCount, warningCount);

        return new PolicyDiagnosticsReport(
            bindingResult.Document.Version,
            bindingResult.Document.Rules.Length,
            errorCount,
            warningCount,
            time,
            bindingResult.Issues,
            recommendations);
    }

    private static ImmutableArray<string> BuildRecommendations(PolicyDocument document, int errorCount, int warningCount)
    {
        var messages = ImmutableArray.CreateBuilder<string>();

        if (errorCount > 0)
        {
            messages.Add("Resolve policy errors before promoting the revision; fallback rules may be applied while errors remain.");
        }

        if (warningCount > 0)
        {
            messages.Add("Review policy warnings and ensure intentional overrides are documented.");
        }

        if (document.Rules.Length == 0)
        {
            messages.Add("Add at least one policy rule to enforce gating logic.");
        }

        var quietRules = document.Rules
            .Where(static rule => rule.Action.Quiet)
            .Select(static rule => rule.Name)
            .ToArray();

        if (quietRules.Length > 0)
        {
            messages.Add($"Quiet rules detected ({string.Join(", ", quietRules)}); verify scoring behaviour aligns with expectations.");
        }

        if (messages.Count == 0)
        {
            messages.Add("Policy validated successfully; no additional action required.");
        }

        return messages.ToImmutable();
    }
}
