using System.Text.Json;

using Microsoft.EntityFrameworkCore;

using Monitoring.Extensions;

public class AssetConcurrencyMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<AssetConcurrencyMiddleware> _logger;

    public AssetConcurrencyMiddleware(RequestDelegate next, ILogger<AssetConcurrencyMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (DbUpdateConcurrencyException ex)
        {
            _logger.LogWarning("Asset concurrency conflict detected. Path: {Path}, User: {User}",
                context.Request.Path, context.User?.Identity?.Name ?? "Anonymous");

            await HandleAssetConcurrencyException(context, ex);
        }
        catch (AssetConcurrencyException ex) 
        {
            _logger.LogWarning("Asset concurrency exception: {Message}", ex.Message);
            await HandleAssetConcurrencyException(context, ex);
        }
    }

    private async Task HandleAssetConcurrencyException(HttpContext context, Exception ex)
    {
        context.Response.Clear();
        context.Response.StatusCode = 409; 
        context.Response.ContentType = "application/json";

        var response = new
        {
            error = "AssetConcurrencyConflict",
            message = "Актив был изменен другим пользователем. Обновите данные и попробуйте снова.",
            timestamp = DateTime.UtcNow,
            details = new
            {
                type = ex.GetType().Name,
                retryRecommended = true,
                retryAfterSeconds = 3
            }
        };

        var json = JsonSerializer.Serialize(response, new JsonSerializerOptions 
        { 
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = true
        });

        await context.Response.WriteAsync(json);
    }
}