using System;
using System.Threading;
using Cysharp.Net.Http;
using eagle;
using Grpc.Core;
using Grpc.Core.Interceptors;
using Grpc.Net.Client;
using Microsoft.Extensions.Logging;
using Net.Eagle0.Eagle.Api;

public class EagleConnection : IDisposable {
    public readonly string playerName;
    public readonly Metadata credentials;
    public readonly string authHeader;
    private const double KeepAliveSeconds = 45.0;

    public static CancellationToken EagleCancellationToken =>
            ConnectionKiller.EagleCancellationToken;

    public Eagle.EagleClient EagleGrpcClient { get; private set; }
    private GrpcChannel _channel;
    private ILoggerFactory _loggerFactory;

    private CallInvoker MakeInvoker(string playerName, string password, string url) {
        var authInterceptor = new AuthInterceptor(playerName, password);

        _channel = GrpcChannel.ForAddress(
                "https://" + url,
                new GrpcChannelOptions {
                    HttpHandler =
                            new YetAnotherHttpHandler {
                                Http2Only = true,
                                Http2KeepAliveInterval = TimeSpan.FromSeconds(KeepAliveSeconds)
                            },
                    DisposeHttpClient = true,
                    LoggerFactory = _loggerFactory,
                    MaxReceiveMessageSize = null
                });

        var invoker = _channel.Intercept(authInterceptor);
        return invoker;
    }

    public EagleConnection(string playerName, string password, string url) {
        this.playerName = playerName;
        credentials = new Metadata { { "user", playerName } };
        authHeader = AuthInterceptor.HeaderValue(playerName, password);

        _loggerFactory = LoggerFactory.Create(
                builder => { builder.AddProvider(new CustomFileLoggerProvider()); });

        EagleGrpcClient = new Eagle.EagleClient(MakeInvoker(playerName, password, url));
    }

    public void Dispose() {
        try {
            _channel?.Dispose();
        } catch (Exception ex) { Console.WriteLine($"Error disposing gRPC channel: {ex.Message}"); }

        try {
            _loggerFactory?.Dispose();
        } catch (Exception ex) {
            Console.WriteLine($"Error disposing logger factory: {ex.Message}");
        }
    }
}
