namespace CashLineERP.Application.Parties;

public sealed class OnboardingReviewApprovalGateService : IOnboardingReviewApprovalGateService
{
    private readonly IOnboardingReviewRepository _repository;

    public OnboardingReviewApprovalGateService(IOnboardingReviewRepository repository)
    {
        _repository = repository;
    }

    public void EnsureApprovalAllowed(string subjectTypeCode, long subjectProfileId)
    {
        var reviewCase = _repository.GetReviewCase(subjectTypeCode, subjectProfileId);

        var blockingChecklistItems = reviewCase.ChecklistItems
            .Where(item => !IsChecklistStatusApproved(item.StatusCode))
            .ToArray();

        if (blockingChecklistItems.Length > 0)
        {
            var blockingCodes = string.Join(", ", blockingChecklistItems.Select(item => item.ChecklistItemCode));
            throw new InvalidOperationException($"Onboarding approval is blocked until required checklist items are resolved: {blockingCodes}.");
        }

        var openFindings = reviewCase.Findings
            .Where(finding => !IsFindingStatusResolved(finding.StatusCode))
            .ToArray();

        if (openFindings.Length > 0)
        {
            var openFindingCodes = string.Join(", ", openFindings.Select(finding => finding.FindingCode));
            throw new InvalidOperationException($"Onboarding approval is blocked while open onboarding findings remain: {openFindingCodes}.");
        }
    }

    private static bool IsChecklistStatusApproved(string statusCode) =>
        string.Equals(statusCode, "ACCEPTED", StringComparison.OrdinalIgnoreCase)
        || string.Equals(statusCode, "WAIVED_WITH_REASON", StringComparison.OrdinalIgnoreCase)
        || string.Equals(statusCode, "NOT_APPLICABLE", StringComparison.OrdinalIgnoreCase);

    private static bool IsFindingStatusResolved(string statusCode) =>
        string.Equals(statusCode, "CLOSED", StringComparison.OrdinalIgnoreCase)
        || string.Equals(statusCode, "RESOLVED", StringComparison.OrdinalIgnoreCase)
        || string.Equals(statusCode, "WAIVED", StringComparison.OrdinalIgnoreCase);
}
