using System;
using System.IO;
using Microsoft.Extensions.Configuration;
using Serilog;
using Topshelf;
using ZB.MOM.WW.LmxProxy.Host.Configuration;

namespace ZB.MOM.WW.LmxProxy.Host
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            // Build configuration
            IConfigurationRoot? configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", true, true)
                .AddEnvironmentVariables()
                .Build();

            // Configure Serilog from appsettings.json
            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration)
                .CreateLogger();

            try
            {
                Log.Information("Starting ZB.MOM.WW.LmxProxy.Host");

                // Load configuration
                var config = new LmxProxyConfiguration();
                configuration.Bind(config);

                // Validate configuration
                if (!ConfigurationValidator.ValidateAndLog(config))
                {
                    Log.Fatal("Configuration validation failed. Please check the configuration and try again.");
                    Environment.ExitCode = 1;
                    return;
                }

                // Configure and run the Windows service using TopShelf
                TopshelfExitCode exitCode = HostFactory.Run(hostConfig =>
                {
                    hostConfig.Service<LmxProxyService>(serviceConfig =>
                    {
                        serviceConfig.ConstructUsing(() => new LmxProxyService(config));
                        serviceConfig.WhenStarted(service => service.Start());
                        serviceConfig.WhenStopped(service => service.Stop());
                        serviceConfig.WhenPaused(service => service.Pause());
                        serviceConfig.WhenContinued(service => service.Continue());
                        serviceConfig.WhenShutdown(service => service.Shutdown());
                    });

                    hostConfig.UseSerilog(Log.Logger);

                    hostConfig.SetServiceName("ZB.MOM.WW.LmxProxy.Host");
                    hostConfig.SetDisplayName("SCADA Bridge LMX Proxy");
                    hostConfig.SetDescription("Provides gRPC access to Archestra MxAccess for SCADA Bridge");

                    hostConfig.StartAutomatically();
                    hostConfig.EnableServiceRecovery(recoveryConfig =>
                    {
                        recoveryConfig.RestartService(config.ServiceRecovery.FirstFailureDelayMinutes);
                        recoveryConfig.RestartService(config.ServiceRecovery.SecondFailureDelayMinutes);
                        recoveryConfig.RestartService(config.ServiceRecovery.SubsequentFailureDelayMinutes);
                        recoveryConfig.SetResetPeriod(config.ServiceRecovery.ResetPeriodDays);
                    });

                    hostConfig.OnException(ex => { Log.Fatal(ex, "Unhandled exception in service"); });
                });

                Log.Information("Service exited with code: {ExitCode}", exitCode);
                Environment.ExitCode = (int)exitCode;
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Failed to start service");
                Environment.ExitCode = 1;
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }
    }
}
