using Knot.Shared.Kernel;
using Knot.Contracts.Settings.Application.Abstractions;
using Knot.Contracts.Settings.Application.DTOs;
using MediatR;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace Knot.Modules.WebRtc.Application.WebRtc.Queries;

public record IceServerDto(string[] Urls, string? Username = null, string? Credential = null);
public record IceServersResultDto(List<IceServerDto> IceServers);

public record GetIceServersQuery : IQuery<IceServersResultDto>;

internal sealed class GetIceServersQueryHandler : IQueryHandler<GetIceServersQuery, IceServersResultDto>
{
    private readonly ISettingsService _settingsService;
    private readonly ILogger<GetIceServersQueryHandler> _logger;

    public GetIceServersQueryHandler(ISettingsService settingsService, ILogger<GetIceServersQueryHandler> logger)
    {
        _settingsService = settingsService;
        _logger = logger;
    }

    public async Task<Result<IceServersResultDto>> Handle(GetIceServersQuery request, CancellationToken cancellationToken)
    {
        var settings = await _settingsService.GetSettingsAsync(cancellationToken);
        var webrtc = settings.WebRtc;

        _logger.LogInformation("WebRTC Config: Enabled={Enabled}, TurnHost={TurnHost}, TurnPort={TurnPort}, HasUser={HasUser}", 
            webrtc.Enabled, webrtc.TurnHost, webrtc.TurnPort, !string.IsNullOrEmpty(webrtc.TurnUser));

        if (!webrtc.Enabled)
        {
            _logger.LogWarning("WebRTC is disabled in server settings. Returning Failure.");
            return Result.Failure<IceServersResultDto>(new Error(
                "WebRtc.Disabled", 
                "WebRTC calls are disabled by the server administrator."));
        }

        var iceServers = new List<IceServerDto>();

        // Если хост TURN задан, формируем STUN и TURN записи
        if (!string.IsNullOrEmpty(webrtc.TurnHost))
        {
            var turnUrl = $"turn:{webrtc.TurnHost}:{webrtc.TurnPort}";
            var stunUrl = $"stun:{webrtc.TurnHost}:{webrtc.TurnPort}";

            // Всегда добавляем STUN (публичный или свой)
            iceServers.Add(new IceServerDto(new[] { stunUrl, "stun:stun.l.google.com:19302" }));

            // Добавляем TURN (TCP и UDP варианты)
            if (!string.IsNullOrEmpty(webrtc.TurnUser))
            {
                _logger.LogInformation("Creating TURN server entry with user {TurnUser}", webrtc.TurnUser);
                iceServers.Add(new IceServerDto(
                    new[] { turnUrl, $"{turnUrl}?transport=tcp" },
                    webrtc.TurnUser,
                    !string.IsNullOrEmpty(webrtc.TurnSecret) ? webrtc.TurnSecret : webrtc.TurnUser
                ));
            }
        }
        else
        {
            _logger.LogInformation("Using public Google STUN fallback because TurnHost is not configured.");
            // Если своего сервера нет, используем публичный Google STUN как fallback
            iceServers.Add(new IceServerDto(new[] { "stun:stun.l.google.com:19302" }));
        }

        _logger.LogInformation("WebRTC: successfully gathered {Count} ICE servers", iceServers.Count);
        return Result.Success(new IceServersResultDto(iceServers));
    }
}
