using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.Extensions.Hosting;
using PlanTempus.Core.Telemetry;

namespace PlanTempus.Core.SeqLogging
{
    public class SeqBackgroundService : BackgroundService
    {
        private readonly IMessageChannel<ITelemetry> _messageChannel;
        private readonly TelemetryClient _telemetryClient;
        private readonly SeqLogger<SeqBackgroundService> _seqLogger;
        private readonly TaskCompletionSource _shutdownComplete = new();

        public SeqBackgroundService(TelemetryClient telemetryClient,
                                    IMessageChannel<ITelemetry> messageChannel,
                                    SeqLogger<SeqBackgroundService> seqlogger)
        {
            _telemetryClient = telemetryClient;
            _messageChannel = messageChannel;
            _seqLogger = seqlogger;

            _telemetryClient.TrackTrace("SeqBackgroundService started");

        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await foreach (var telemetry in _messageChannel.Reader.ReadAllAsync())
            {
                try
                {
                    switch (telemetry)
                    {
                        case StopTelemetry:
                            StopGracefully();
                            return;

                        case ExceptionTelemetry et:
                            await _seqLogger.LogAsync(et);
                            break;

                        case TraceTelemetry et:
                            await _seqLogger.LogAsync(et);
                            break;

                        case DependencyTelemetry et:
                            await _seqLogger.LogAsync(et);
                            break;

                        case RequestTelemetry et:
                            await _seqLogger.LogAsync(et);
                            break;

                        case EventTelemetry et:
                            await _seqLogger.LogAsync(et);
                            break;

                        default:
                            throw new NotSupportedException(telemetry.GetType().Name);
                    }
                }
                catch (Exception)
                {
                    // Ignore errors processing telemetry
                }
            }
        }

        public override async Task StopAsync(CancellationToken cancellationToken)
        {
            _messageChannel.Writer.TryWrite(new StopTelemetry());

            // Vent max 10 sekunder på graceful shutdown
            await Task.WhenAny(_shutdownComplete.Task, Task.Delay(10000));

            await base.StopAsync(cancellationToken);
        }

        private void StopGracefully()
        {
            _messageChannel.Dispose();
            _shutdownComplete.SetResult();
        }
    }
}
