using Insight.Domain.Enums;
using Insight.Domain.Interfaces;
using Insight.Domain.Network;
using Insight.Domain.Network.Remote.Messages;
using Insight.Remote.Shared.Messages;
using Microsoft.Extensions.Logging;
using System.ServiceProcess;
using Vaitr.Bus;
using Vaitr.Network;

namespace Insight.Remote.Shared.Network;

public class RemoteSession : TcpSession<IMessage>
{
    public string? Id { get; set; }
    public string? AccessKey { get; set; }
    public RemoteControlMode Mode { get; } = RunningAsService() ? RemoteControlMode.Unattended : RemoteControlMode.Attended;

    private readonly Bus _bus;
    private readonly IEnumerable<IMessageHandler<RemoteSession>> _handlers;

    public RemoteSession(Bus bus, IEnumerable<IMessageHandler<RemoteSession>> handlers, ISerializer<IMessage> serializer, ILogger<RemoteSession> logger) : base(serializer, logger)
    {
        _bus = bus;
        _handlers = handlers;
    }

    protected override async ValueTask OnConnectedAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Remote ({ep?}) connected", RemoteEndPoint);

        await _bus.PublishAsync(new ConnectionStateChanged(ConnectionState.Connected), cancellationToken);

        await SendAsync(new RemoteSessionRequest
        {
            Hostname = "Debug Host",
            Mode = RemoteControlMode.Attended
        }, cancellationToken);
    }

    protected override async ValueTask OnDisconnectedAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Remote ({ep?}) disconnected", RemoteEndPoint);

        await _bus.PublishAsync(new ConnectionStateChanged(ConnectionState.Disconnected));
    }

    protected override async ValueTask OnSentAsync(IPacketContext<IMessage> context, CancellationToken cancellationToken)
    {
        //await base.OnSentAsync(context, cancellationToken);
    }

    protected override async ValueTask OnReceivedAsync(IPacketContext<IMessage> context, CancellationToken cancellationToken)
    {
        //await base.OnReceivedAsync(context, cancellationToken);

        foreach (var handler in _handlers)
        {
            try
            {
                await handler.HandleAsync(this, context.Packet, cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogWarning("Remote ({ep?}) {ex}", RemoteEndPoint, ex.ToString());
            }
        }
    }

    protected override async ValueTask OnHeartbeatAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Remote ({ep?}) Heartbeat", RemoteEndPoint);
    }

    private async ValueTask OnWindowsSessionSwitchedAsync(WindowsSessionSwitched message, CancellationToken cancellationToken)
    {
        try
        {
            //await SendAsync(new NotifySessionChanged(message.SessionId, message.Reason), cancellationToken);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.Message);
        }
    }

    private async ValueTask OnWindowsSessionEndingAsync(WindowsSessionEnding message, CancellationToken cancellationToken)
    {
        //await DisconnectViewersAsync();
    }

    private static bool RunningAsService()
    {
        return false;

        if (OperatingSystem.IsWindows())
        {
            return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals("remotecontrol"));
        }

        return false;
    }
}