using System;
using System.IO;
using System.ServiceProcess;
using CncCollector.Config;
using CncCollector.Core;
using CncCollector.Api;
using log4net;

namespace CncCollector
{
    /// <summary>
    /// CNC机床数据采集服务主入口。
    /// 支持三种运行模式：
    ///   1. Windows Service 模式（由 SCM 启动，无参数）
    ///   2. 控制台交互模式（带 --console 参数）
    ///   3. 服务安装/卸载（带 --install / --uninstall 参数）
    /// </summary>
    class Program
    {
        private static readonly ILog _log = LogManager.GetLogger(typeof(Program));

        static void Main(string[] args)
        {
            // 初始化log4net
            InitLog4Net();

            // 解析命令行参数
            bool runAsConsole = false;
            bool installService = false;
            bool uninstallService = false;

            foreach (var arg in args)
            {
                var lower = arg.ToLower().TrimStart('-', '/');
                if (lower == "console") runAsConsole = true;
                else if (lower == "install") installService = true;
                else if (lower == "uninstall") uninstallService = true;
            }

            // 模式1：服务安装
            if (installService)
            {
                InstallService();
                return;
            }

            // 模式2：服务卸载
            if (uninstallService)
            {
                UninstallService();
                return;
            }

            // 模式3：控制台交互模式
            if (runAsConsole || Environment.UserInteractive)
            {
                RunConsole();
                return;
            }

            // 模式4：Windows Service 模式（由 SCM 调用）
            RunAsService();
        }

        /// <summary>
        /// 初始化log4net日志
        /// </summary>
        private static void InitLog4Net()
        {
            var logConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4net.config");
            if (File.Exists(logConfig))
            {
                log4net.Config.XmlConfigurator.Configure(new FileInfo(logConfig));
                return;
            }
            // 开发模式：从项目根目录读取
            logConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "log4net.config");
            if (File.Exists(logConfig))
                log4net.Config.XmlConfigurator.Configure(new FileInfo(logConfig));
        }

        /// <summary>
        /// 控制台交互模式：手动启停，按任意键退出
        /// </summary>
        private static void RunConsole()
        {
            Console.WriteLine("CNC 机床数据采集服务 v1.0（控制台模式）");
            Console.WriteLine("================================================");

            // 加载配置
            CollectorConfig config;
            try
            {
                config = CollectorConfig.Load();
                _log.Info("配置文件加载成功");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"错误: 加载配置文件失败 - {ex.Message}");
                _log.Fatal("加载配置文件失败", ex);
                Console.WriteLine("按任意键退出...");
                Console.ReadKey();
                return;
            }

            // 从数据库加载运行时配置
            try
            {
                ConfigLoader.LoadRuntimeConfig(config.BusinessConnection, config);
            }
            catch (Exception ex)
            {
                _log.Warn("从数据库加载配置失败，使用文件默认值", ex);
                Console.WriteLine($"  [!] 数据库配置加载失败: {ex.Message}");
            }

            // 创建引擎和API
            var engine = new CollectorEngine(config);
            var apiServer = new CollectorApiServer(engine, config.ApiKey, config.ApiPort);

            // 启动
            engine.Start();
            apiServer.Start();

            Console.WriteLine($"\n管理API: http://localhost:{config.ApiPort}/api/collector/status");
            Console.WriteLine($"API Key: {config.ApiKey}");
            Console.WriteLine($"\n按任意键退出...");

            // 注册 Ctrl+C 优雅退出
            Console.CancelKeyPress += (sender, e) =>
            {
                e.Cancel = true;
                Console.WriteLine("\n正在停止...");
                apiServer.Stop();
                engine.Stop();
            };

            Console.ReadKey();

            // 退出
            engine.Stop();
            apiServer.Stop();

            _log.Info("采集服务已退出");
            Console.WriteLine("已退出。");
        }

        /// <summary>
        /// Windows Service 模式：交给 ServiceBase.Run 管理
        /// </summary>
        private static void RunAsService()
        {
            _log.Info("以 Windows Service 模式启动");
            ServiceBase[] servicesToRun = new ServiceBase[]
            {
                new CncCollectorService()
            };
            ServiceBase.Run(servicesToRun);
        }

        /// <summary>
        /// 使用 InstallUtil 安装服务
        /// </summary>
        private static void InstallService()
        {
            Console.WriteLine("正在安装 CNC 采集服务...");
            try
            {
                var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
                var installUtilPath = FindInstallUtil();
                if (installUtilPath == null)
                {
                    // 降级到 sc.exe
                    Console.WriteLine("未找到 InstallUtil，使用 sc.exe 安装...");
                    InstallWithSc(exePath);
                    return;
                }

                var psi = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = installUtilPath,
                    Arguments = $"\"{exePath}\"",
                    Verb = "runas",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };

                using (var proc = System.Diagnostics.Process.Start(psi))
                {
                    proc.WaitForExit();
                    Console.WriteLine(proc.StandardOutput.ReadToEnd());
                    if (proc.ExitCode != 0)
                    {
                        Console.WriteLine("安装失败！");
                        Console.WriteLine(proc.StandardError.ReadToEnd());
                        Environment.Exit(proc.ExitCode);
                    }
                }

                Console.WriteLine("服务安装成功！使用 Start-Service CncCollector 启动。");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"安装失败: {ex.Message}");
                Environment.Exit(1);
            }
        }

        /// <summary>
        /// 使用 InstallUtil 卸载服务
        /// </summary>
        private static void UninstallService()
        {
            Console.WriteLine("正在卸载 CNC 采集服务...");
            try
            {
                // 先尝试停止服务
                var svc = ServiceController.GetServices();
                foreach (var s in svc)
                {
                    if (s.ServiceName == CncCollectorService.ServiceNameConst)
                    {
                        if (s.Status == ServiceControllerStatus.Running)
                        {
                            Console.WriteLine("正在停止服务...");
                            s.Stop();
                            s.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));
                        }
                        break;
                    }
                }

                var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
                var installUtilPath = FindInstallUtil();
                if (installUtilPath == null)
                {
                    Console.WriteLine("未找到 InstallUtil，使用 sc.exe 卸载...");
                    UninstallWithSc();
                    return;
                }

                var psi = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = installUtilPath,
                    Arguments = $"/u \"{exePath}\"",
                    Verb = "runas",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };

                using (var proc = System.Diagnostics.Process.Start(psi))
                {
                    proc.WaitForExit();
                    Console.WriteLine(proc.StandardOutput.ReadToEnd());
                    if (proc.ExitCode != 0)
                    {
                        Console.WriteLine("卸载失败！");
                        Console.WriteLine(proc.StandardError.ReadToEnd());
                        Environment.Exit(proc.ExitCode);
                    }
                }

                Console.WriteLine("服务卸载成功。");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"卸载失败: {ex.Message}");
                Environment.Exit(1);
            }
        }

        /// <summary>
        /// 查找 InstallUtil.exe 路径
        /// </summary>
        private static string FindInstallUtil()
        {
            try
            {
                var runtimeDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
                var path = Path.Combine(runtimeDir, "InstallUtil.exe");
                if (File.Exists(path)) return path;
            }
            catch { }

            // 尝试 .NET Framework 4 目录
            var frameworkPath = Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.Windows),
                @"Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe");
            if (File.Exists(frameworkPath)) return frameworkPath;

            frameworkPath = Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.Windows),
                @"Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe");
            if (File.Exists(frameworkPath)) return frameworkPath;

            return null;
        }

        /// <summary>
        /// 使用 sc.exe 安装服务（InstallUtil 不可用时的降级方案）
        /// </summary>
        private static void InstallWithSc(string exePath)
        {
            var psi = new System.Diagnostics.ProcessStartInfo
            {
                FileName = "sc.exe",
                Arguments = $"create {CncCollectorService.ServiceNameConst} binPath= \"{exePath}\" start= auto DisplayName= \"CNC 机床数据采集服务\"",
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true
            };

            using (var proc = System.Diagnostics.Process.Start(psi))
            {
                proc.WaitForExit();
                Console.WriteLine(proc.StandardOutput.ReadToEnd());
                if (proc.ExitCode != 0)
                {
                    Console.WriteLine("sc.exe 安装失败！");
                    Environment.Exit(proc.ExitCode);
                }
            }

            // 设置描述
            var descPsi = new System.Diagnostics.ProcessStartInfo
            {
                FileName = "sc.exe",
                Arguments = $"description {CncCollectorService.ServiceNameConst} \"CNC机床HTTP采集、数据解析、产量跟踪和日终汇总\"",
                UseShellExecute = false
            };
            using (var proc = System.Diagnostics.Process.Start(descPsi))
            {
                proc.WaitForExit();
            }

            Console.WriteLine("服务安装成功（sc.exe）！使用 Start-Service CncCollector 启动。");
        }

        /// <summary>
        /// 使用 sc.exe 卸载服务（InstallUtil 不可用时的降级方案）
        /// </summary>
        private static void UninstallWithSc()
        {
            var psi = new System.Diagnostics.ProcessStartInfo
            {
                FileName = "sc.exe",
                Arguments = $"delete {CncCollectorService.ServiceNameConst}",
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true
            };

            using (var proc = System.Diagnostics.Process.Start(psi))
            {
                proc.WaitForExit();
                Console.WriteLine(proc.StandardOutput.ReadToEnd());
                if (proc.ExitCode != 0)
                {
                    Console.WriteLine("sc.exe 卸载失败！");
                    Environment.Exit(proc.ExitCode);
                }
            }

            Console.WriteLine("服务卸载成功（sc.exe）。");
        }
    }
}
