using Tiku.Api.Controllers;
using Tiku.Api.Middleware;
using Tiku.Application.Tenancy;
using Tiku.Application.Security;

namespace Tiku.Api.Modules.Tenant.Tenancy.Errors;

internal sealed class TenancyExceptionProblemDetailsMapper : ExceptionProblemDetailsMapper
{
    public override IReadOnlyCollection<Type> HandledExceptionTypes { get; } =
    [
        typeof(TenantNotFoundException), typeof(TenantLifecycleException), typeof(TenantContextConflictException),
        typeof(TenantFrontendConfigException), typeof(TenantExternalProviderException)
    ];

    public override bool TryMap(Exception exception, out ExceptionProblemDetailsMapping mapping)
    {
        return exception switch
        {
            TenantNotFoundException => Mapped(exception, StatusCodes.Status404NotFound, "tenant_not_found",
                out mapping),
            TenantLifecycleException lifecycle => Mapped(lifecycle, LifecycleStatus(lifecycle.Code), lifecycle.Code,
                out mapping),
            TenantContextConflictException => Mapped(exception, StatusCodes.Status403Forbidden,
                "tenant_context_conflict", out mapping),
            TenantFrontendConfigException frontend => Mapped(frontend, FrontendStatus(frontend.Code), frontend.Code,
                out mapping),
            TenantExternalProviderException provider => Mapped(provider, StatusCodes.Status400BadRequest, provider.Code,
                out mapping),
            _ => NotMapped(out mapping)
        };
    }

    private static int LifecycleStatus(string code)
    {
        return code switch
        {
            "tenant_not_found" => StatusCodes.Status404NotFound,
            "tenant_export_not_ready" or "tenant_archive_blocked" or "tenant_not_archived" or
                "tenant_owner_target_not_active_member" or "tenant_owner_unchanged" => StatusCodes.Status409Conflict,
            _ => StatusCodes.Status400BadRequest
        };
    }

    private static int FrontendStatus(string code)
    {
        return code switch
        {
            "tenant_not_found" or "frontend_config_not_found" => StatusCodes.Status404NotFound,
            "frontend_config_version_conflict" => StatusCodes.Status409Conflict,
            _ => StatusCodes.Status400BadRequest
        };
    }
}
