using System;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.ServiceProcess;
using System.Threading;

namespace NoticeServer
{
    partial class Program
    {
        static TcpChatServer tcpServer;
        static bool isRunning = true;

        static void Main(string[] args)
        {
            // 명령행 인수 처리
            if (args.Length > 0)
            {
                string command = args[0].ToLower();
                switch (command)
                {
                    case "-install":
                    case "/install":
                        InstallService();
                        return;
                    case "-uninstall":
                    case "/uninstall":
                        UninstallService();
                        return;
                    case "-console":
                    case "/console":
                        RunAsConsole();
                        return;
                    case "-help":
                    case "/help":
                    case "/?":
                        ShowHelp();
                        return;
                }
            }

            // 서비스로 실행
            if (Environment.UserInteractive)
            {
                // 대화형 모드에서는 콘솔로 실행
                RunAsConsole();
            }
            else
            {
                // 서비스로 실행
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[]
                {
                    new NoticeService()
                };
                ServiceBase.Run(ServicesToRun);
            }
        }

        private static void ShowHelp()
        {
            Console.WriteLine("EETGW Notice Server (Chat Server)");
            Console.WriteLine("사용법:");
            Console.WriteLine("  NoticeServer.exe               - 서비스로 실행 (또는 대화형 모드에서 콘솔 실행)");
            Console.WriteLine("  NoticeServer.exe -console      - 콘솔 모드로 실행");
            Console.WriteLine("  NoticeServer.exe -install      - 서비스 설치");
            Console.WriteLine("  NoticeServer.exe -uninstall    - 서비스 제거");
            Console.WriteLine("  NoticeServer.exe -help         - 도움말 표시");
        }

        private static void InstallService()
        {
            try
            {
                string servicePath = $"\"{System.Reflection.Assembly.GetExecutingAssembly().Location}\"";
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = "sc.exe",
                    Arguments = $"create EETGWNoticeService binPath= \"{servicePath}\" DisplayName= \"EETGW Notice Service\" start= auto",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                };

                using (Process process = Process.Start(startInfo))
                {
                    process.WaitForExit();
                    if (process.ExitCode == 0)
                    {
                        Console.WriteLine("서비스가 성공적으로 설치되었습니다.");
                        Console.WriteLine("서비스를 시작하려면 다음 명령을 실행하세요:");
                        Console.WriteLine("net start EETGWNoticeService");
                    }
                    else
                    {
                        string error = process.StandardError.ReadToEnd();
                        Console.WriteLine($"서비스 설치 실패: {error}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"서비스 설치 중 오류 발생: {ex.Message}");
            }
        }

        private static void UninstallService()
        {
            try
            {
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = "sc.exe",
                    Arguments = "delete EETGWNoticeService",
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                };

                using (Process process = Process.Start(startInfo))
                {
                    process.WaitForExit();
                    if (process.ExitCode == 0)
                    {
                        Console.WriteLine("서비스가 성공적으로 제거되었습니다.");
                    }
                    else
                    {
                        string error = process.StandardError.ReadToEnd();
                        Console.WriteLine($"서비스 제거 실패: {error}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"서비스 제거 중 오류 발생: {ex.Message}");
            }
        }

        private static void RunAsConsole()
        {
            // 중복실행 방지 체크
            if (!CheckSingleInstance())
            {
                return; // 프로그램 종료
            }

            Console.OutputEncoding = System.Text.Encoding.UTF8;
            Console.Title = "EETGW Notice Server (Chat Server)";
            Console.WriteLine("========================================");
            Console.WriteLine("  EETGW Notice Server v1.0 (콘솔 모드)");
            Console.WriteLine("========================================\n");

            // Read settings
            int tcpPort = Properties.Settings.Default.TcpPort;
            int maxClients = Properties.Settings.Default.MaxClients;

            // Get local IP address
            string localIP = GetLocalIPAddress();
            string hostName = Dns.GetHostName();

            Console.WriteLine($"Server IP: {localIP}");
            Console.WriteLine($"Host Name: {hostName}");
            Console.WriteLine($"TCP Port: {tcpPort}");
            Console.WriteLine($"Max Clients: {maxClients}\n");

            // Start server
            tcpServer = new TcpChatServer(tcpPort, maxClients);
            tcpServer.Start();

            Console.WriteLine("\nServer started successfully.");
            Console.WriteLine("Commands: status, clear, quit, help");
            Console.WriteLine("종료하려면 Ctrl+C를 누르거나 'quit'를 입력하세요.\n");

            // Ctrl+C handler
            Console.CancelKeyPress += (sender, e) =>
            {
                Console.WriteLine("\n서버를 종료합니다...");
                e.Cancel = true;
                isRunning = false;
            };

            // Command processing loop
            while (isRunning)
            {
                string command = Console.ReadLine()?.Trim().ToLower();

                switch (command)
                {
                    case "status":
                    case "s":
                        tcpServer.PrintStatus();
                        break;

                    case "clear":
                    case "cls":
                        Console.Clear();
                        Console.WriteLine("EETGW Notice Server - Commands: status, clear, quit\n");
                        break;

                    case "quit":
                    case "exit":
                    case "q":
                        isRunning = false;
                        break;

                    case "help":
                    case "h":
                    case "?":
                        PrintHelp();
                        break;

                    case "":
                        break;

                    default:
                        Console.WriteLine($"Unknown command: {command}");
                        Console.WriteLine("Available commands: status, clear, quit, help");
                        break;
                }

                Thread.Sleep(100);
            }

            // Server shutdown
            Console.WriteLine("\nShutting down server...");
            tcpServer.Stop();

            Console.WriteLine("Server stopped.");
            Thread.Sleep(1000);
        }

        /// <summary>
        /// 중복실행 방지 체크
        /// </summary>
        /// <returns>단일 인스턴스인 경우 true, 중복실행인 경우 false</returns>
        static bool CheckSingleInstance()
        {
            string processName = Process.GetCurrentProcess().ProcessName;
            Process[] processes = Process.GetProcessesByName(processName);

            if (processes.Length > 1)
            {
                // 중복실행 감지
                string message = $"⚠️ 프로그램이 이미 실행 중입니다!\n\n" +
                                "동시에 여러 개의 프로그램을 실행할 수 없습니다.\n";

                Console.WriteLine(message);
                return false;
            }

            return true; // 단일 인스턴스
        }

        static string GetLocalIPAddress()
        {
            try
            {
                var host = Dns.GetHostEntry(Dns.GetHostName());
                var ipAddress = host.AddressList
                    .FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);

                if (ipAddress != null)
                    return ipAddress.ToString();
            }
            catch { }

            return "127.0.0.1";
        }

        static void PrintHelp()
        {
            Console.WriteLine("\n========================================");
            Console.WriteLine("Available Commands:");
            Console.WriteLine("========================================");
            Console.WriteLine("status (s)  - Show server status and client list");
            Console.WriteLine("clear (cls) - Clear screen");
            Console.WriteLine("quit (q)    - Stop server");
            Console.WriteLine("help (h)    - Show this help");
            Console.WriteLine("========================================\n");
        }
    }
}
