using Tiku.Api.Middleware;
using Tiku.Application.Backoffice;
using Tiku.Application.PlatformAdmin;
using Tiku.Application.PlatformBilling;

namespace Tiku.Api.Modules.Platform.Errors;

internal sealed class PlatformExceptionProblemDetailsMapper : ExceptionProblemDetailsMapper
{
    public override IReadOnlyCollection<Type> HandledExceptionTypes { get; } =
    [
        typeof(PlatformApprovalException), typeof(BackofficeException), typeof(PlatformAdminException),
        typeof(PlatformBillingException), typeof(PlatformCapabilityException)
    ];

    public override bool TryMap(Exception exception, out ExceptionProblemDetailsMapping mapping)
    {
        return exception switch
        {
            PlatformApprovalException approval => Mapped(approval, ApprovalStatus(approval.Code), approval.Code,
                out mapping),
            BackofficeException backoffice => Mapped(backoffice, BackofficeStatus(backoffice.Code), backoffice.Code,
                out mapping),
            PlatformAdminException admin => Mapped(admin, AdminStatus(admin.Code), admin.Code, out mapping),
            PlatformBillingException billing => Mapped(billing, BillingStatus(billing.Code), billing.Code, out mapping),
            PlatformCapabilityException capability => Mapped(capability, StatusCodes.Status400BadRequest,
                capability.Code, out mapping),
            _ => NotMapped(out mapping)
        };
    }

    private static int ApprovalStatus(string code) => code switch
    {
        "approval_request_not_found" or "approval_policy_not_found" => StatusCodes.Status404NotFound,
        "platform_access_denied" or "approval_business_permission_required" or "approval_cancel_denied" =>
            StatusCodes.Status403Forbidden,
        "approval_request_not_pending" or "approval_request_expired" or "approval_maker_checker_required" or
            "idempotency_conflict" => StatusCodes.Status409Conflict,
        _ => StatusCodes.Status400BadRequest
    };

    private static int BackofficeStatus(string code) => code switch
    {
        "platform_access_denied" or "tenant_access_denied" or "capability_not_available" =>
            StatusCodes.Status403Forbidden,
        _ when code.EndsWith("_not_found", StringComparison.Ordinal) => StatusCodes.Status404NotFound,
        _ => StatusCodes.Status400BadRequest
    };

    private static int AdminStatus(string code) => code switch
    {
        "platform_access_denied" => StatusCodes.Status403Forbidden,
        "tenant_slug_exists" or "idempotency_conflict" or "owner_activation_already_issued" or
            "owner_already_activated" => StatusCodes.Status409Conflict,
        _ when code.EndsWith("_not_found", StringComparison.Ordinal) => StatusCodes.Status404NotFound,
        _ => StatusCodes.Status400BadRequest
    };

    private static int BillingStatus(string code) => code switch
    {
        "tenant_not_found" => StatusCodes.Status404NotFound,
        "platform_billing_public_url_missing" or "payment_provider_not_configured" or
            "payment_secret_not_configured" => StatusCodes.Status503ServiceUnavailable,
        "saas_offering_version_immutable" or "saas_offering_version_status_invalid" or
            "platform_billing_quote_expired" or "platform_billing_order_status_invalid" or
            "platform_billing_payment_status_invalid" or "platform_billing_payment_amount_mismatch" or
            "platform_billing_order_not_cancellable" or "platform_billing_payment_not_refundable" or
            "platform_billing_refund_amount_invalid" or "platform_billing_refund_not_retryable" or
            "platform_billing_refund_status_invalid" or "tenant_saas_subscription_status_invalid" or
            "tenant_saas_subscription_exists" or "idempotency_conflict" => StatusCodes.Status409Conflict,
        _ when code.EndsWith("_not_found", StringComparison.Ordinal) => StatusCodes.Status404NotFound,
        _ => StatusCodes.Status400BadRequest
    };
}
