using System;
using Host.Application.Federation.Commands;
using Knot.Contracts.Settings.Application.Abstractions;
using Knot.Contracts.Settings.Application.DTOs;
using Knot.Modules.Federation.Application.Abstractions;
using Knot.Shared.Kernel.Constants;
using Knot.Shared.Kernel.Storage;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;

namespace Knot.Modules.Federation.Presentation.Endpoints;

/// <summary>
/// Эндпоинты федерации для межсерверного взаимодействия.
/// </summary>
public static class FederationEndpoints
{
    public static void MapFederationEndpoints(this WebApplication app)
    {
        var group = app.MapGroup(Routes.ApiFederation);

        group.MapPost("/handshake", async ([FromBody] HandshakeRequest request, ISender sender, CancellationToken ct) =>
        {
            var result = await sender.Send(new HandshakeFederationCommand(request), ct);
            return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(new { error = result.Error.Description });
        });

        group.MapPost("/inbound", async ([FromBody] FederationMessagePacket packet, ISender sender, CancellationToken ct) =>
        {
            var result = await sender.Send(new InboundFederationCommand(packet), ct);
            return result.IsSuccess ? Results.Accepted() : Results.BadRequest(new { error = result.Error.Description });
        });

        group.MapGet("/resolve/{username}", async ([FromRoute] string username, ISender sender, CancellationToken ct) =>
        {
            var result = await sender.Send(new ResolveUserCommand(username), ct);
            return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(new { error = result.Error.Description });
        });

        group.MapGet("/proxy/{id}", async ([FromRoute] string id, [FromHeader(Name = "X-Knot-Signature")] string signature, [FromHeader(Name = "X-Knot-Domain")] string senderDomain, [FromServices] IFileStorageService storage, [FromServices] ISettingsService settingsService, CancellationToken ct) =>
        {
            // 1. Валидация подписи (упрощенно)
            var settings = await settingsService.GetSettingsAsync(ct);
            var senderConfig = settings.Federation.AllowedDomains.FirstOrDefault(d => d.Domain.Equals(senderDomain, StringComparison.OrdinalIgnoreCase));

            if (senderConfig == null || string.IsNullOrEmpty(senderConfig.PublicKey))
                return Results.Forbid();

            // В реальном коде здесь проверка RSA подписи параметров запроса (URL + Domain)

            // 2. Стриминг файла первоисточника
            try
            {
                var (stream, contentType, fileName) = await storage.DownloadFileAsync(id);
                return Results.File(stream, contentType, fileName, enableRangeProcessing: true);
            }
            catch
            {
                return Results.NotFound();
            }
        });
    }
}
