namespace KArtSell.Modules.ModelOperations.Features.ApprovalWorkflow;

using KArtSell.Modules.ModelOperations.Domain.ApprovalWorkflow;

public static class ApprovalWorkflowPolicy
{
    public static bool CanCreateProposal(string userEmail, string userRole) =>
        userRole.Equals("Maker", StringComparison.OrdinalIgnoreCase);

    public static bool CanProposeForReview(ApprovalProposal proposal, string userEmail) =>
        proposal.CreatedBy == userEmail && proposal.Status == ApprovalStatus.Draft;

    public static bool CanApprove(ApprovalProposal proposal, string userEmail, string userRole)
    {
        if (!userRole.Equals("Checker", StringComparison.OrdinalIgnoreCase))
            return false;

        if (proposal.Status != ApprovalStatus.Proposed)
            return false;

        if (proposal.CreatedBy == userEmail)
            return false; // Separation of duties

        return true;
    }

    public static bool CanActivate(ApprovalProposal proposal, string userEmail, string userRole) =>
        userRole.Equals("SRE", StringComparison.OrdinalIgnoreCase) && proposal.Status == ApprovalStatus.Approved;

    public static ApprovalEvent CreateStateChangeEvent(Guid proposalId, ApprovalStatus newStatus, string userEmail, Guid correlationId, DateTime now, Dictionary<string, object>? details = null)
    {
        var eventType = newStatus switch
        {
            ApprovalStatus.Draft => "CREATED",
            ApprovalStatus.Proposed => "PROPOSED",
            ApprovalStatus.Approved => "APPROVED",
            ApprovalStatus.Active => "ACTIVATED",
            ApprovalStatus.Rejected => "REJECTED",
            _ => "UNKNOWN"
        };

        return new ApprovalEvent
        {
            Id = Guid.NewGuid(),
            ApprovalProposalId = proposalId,
            EventType = eventType,
            ActorEmail = userEmail,
            EventAt = now,
            Details = details,
            PublishedAt = now,
            CorrelationId = correlationId
        };
    }

    public static void ValidateProposalState(ApprovalStatus from, ApprovalStatus to)
    {
        var validTransitions = new Dictionary<ApprovalStatus, List<ApprovalStatus>>
        {
            { ApprovalStatus.Draft, new() { ApprovalStatus.Proposed, ApprovalStatus.Rejected } },
            { ApprovalStatus.Proposed, new() { ApprovalStatus.Approved, ApprovalStatus.Rejected } },
            { ApprovalStatus.Approved, new() { ApprovalStatus.Active, ApprovalStatus.Rejected } },
            { ApprovalStatus.Active, new() { ApprovalStatus.Active } },
            { ApprovalStatus.Rejected, new() { ApprovalStatus.Draft } }
        };

        if (!validTransitions.TryGetValue(from, out var allowed) || !allowed.Contains(to))
            throw new InvalidOperationException($"Invalid state transition: {from} → {to}");
    }
}
