using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.NetworkInformation;
using System.Net;
using System.IO.Compression;
using System.IO;
using FCOMMON;
using System.Diagnostics;

namespace Project.Dialog
{
    public partial class fSystemCheck : Form
    {
        private Timer checkTimer;
        public bool environmentCheckCompleted = false;
        
        public fSystemCheck()
        {
            InitializeComponent();
            
            // 폼 설정
            this.Text = "GroupWare 시작 중...";
            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            this.ControlBox = false;
            this.ShowInTaskbar = false;
            this.TopMost = true;
            
            // 타이머 설정
            checkTimer = new Timer();
            checkTimer.Interval = 100; // 0.1초
            checkTimer.Tick += CheckTimer_Tick;
            checkTimer.Start();

            this.Load += FSystemCheck_Load;
        }

        private void FSystemCheck_Load(object sender, EventArgs e)
        {
            // 환경 체크 시작
            this.Show();
            Application.DoEvents();
            Task.Run(() => PerformEnvironmentCheck());
        }

        private void SafeInvoke(Action action)
        {
            if (this.IsHandleCreated)
            {
                if (this.InvokeRequired)
                    this.Invoke(action);
                else
                    action();
            }
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            checkTimer?.Stop();
            checkTimer?.Dispose();
            if (components != null)
            {
                components.Dispose();
            }
        }
        private void CheckTimer_Tick(object sender, EventArgs e)
        {
            if (environmentCheckCompleted)
            {
                checkTimer.Stop();
                this.Hide();
                
                // fWarning 폼 닫기
                this.Close();
            }
        }
        
        /// <summary>
        /// 실행환경 체크 수행
        /// </summary>
        private async void PerformEnvironmentCheck()
        {
            try
            {
                // UI 업데이트
                this.Invoke(new Action(() => {
                    label1.Text = "🔍 실행환경을 검사하고 있습니다...";
                }));
                
                await Task.Delay(500);

             
                // 1. Pub 초기화
                SafeInvoke(() => {
                    label1.Text = "⚙️ 시스템 초기화 중...";
                });
                
                Pub.init();
                await Task.Delay(300);


                // 0. WebView2Runtime 압축해제 체크
                SafeInvoke(() => {
                    label1.Text = "🌐 WebView2 Runtime 확인 중...";
                });
                await CheckAndExtractWebView2Runtime();
             

                // 2. WebView2 초기화 (메인 스레드에서 실행)
                SafeInvoke(() => {
                    label1.Text = "🌐 WebView2 초기화 중...";
                    try
                    {
                        Pub.InitializeWebView2();
                    }
                    catch (Exception ex)
                    {
                        // COM 스레드 모드 오류 처리
                        if (ex.Message.Contains("RPC_E_CHANGED_MODE") || ex.Message.Contains("스레드 모드"))
                        {
                            Console.WriteLine($"WebView2 초기화 COM 오류 (무시됨): {ex.Message}");
                            // 이 오류는 무시하고 계속 진행 (fMain에서 다시 시도)
                        }
                        else
                        {
                            Console.WriteLine($"WebView2 초기화 오류: {ex.Message}");
                            // 다른 심각한 오류는 무시하고 계속 (fMain에서 처리)
                        }
                    }
                });
                await Task.Delay(500);
                
                // 3. 데이터베이스 접속 정보 확인
                SafeInvoke(() => {
                    label1.Text = "🗄️ 데이터베이스 연결 확인 중...";
                });
                
                CheckDatabaseConnection();
                await Task.Delay(300);
                
                //// 4. 포트 7979 사용 여부 체크
                //SafeInvoke(() => {
                //    label1.Text = "🔌 포트 7979 상태 확인 중...";
                //});
                
                //CheckPort7979InUse();
                //await Task.Delay(300);
                
                // 5. 바코드 설정
                SafeInvoke(() => {
                    label1.Text = "📊 바코드 설정 초기화 중...";
                });
                
                InitializeBarcodeSettings();
                await Task.Delay(300);
                
                // 6. 웹서버 시작 시뮬레이션 (실제 시작은 fMain에서)
                SafeInvoke(() => {
                    label1.Text = "🚀 웹서버 준비 중...";
                });
                
                await Task.Delay(500);
                
                // 7. SqlServerTypes 라이브러리 로드
                SafeInvoke(() => {
                    label1.Text = "📚 Reporting System 로드 중...";
                });
                
                SqlServerTypes.Utilities.LoadNativeAssemblies(AppDomain.CurrentDomain.BaseDirectory);
                await Task.Delay(300);
                
                // 완료
                SafeInvoke(() => {
                    label1.Text = "✅ 실행환경 검사 완료";
                });
                
                await Task.Delay(500);
                environmentCheckCompleted = true;
            }
            catch (Exception ex)
            {
                var st = new System.Diagnostics.StackTrace(ex, true);
                var frame = st.GetFrame(0);
                var fileName = frame?.GetFileName() ?? "Unknown";
                var lineNumber = frame?.GetFileLineNumber() ?? 0;
                var errorMsg = $"실행환경 검사 중 오류가 발생했습니다:\n{ex.Message}\n\n파일: {System.IO.Path.GetFileName(fileName)}\n줄수: {lineNumber}";
                
                SafeInvoke(() => {
                    MessageBox.Show(errorMsg, "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Application.Exit();
                });
            }
        }
        
        /// <summary>
        /// 데이터베이스 연결 확인
        /// </summary>
        private void CheckDatabaseConnection()
        {
            Pub.dbinfo = DatabaseConnectionString.Utility.Read();
            if (Pub.dbinfo.IsValid == false)
            {
                this.Invoke(new Action(() => {
                    this.Visible = false;
                    MessageBox.Show("데이터베이스 접속정보가 존재하지 않습니다\n개발부서에 접속정보를 문의하세요", 
                                   "Alert", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    
                    Pub.dbinfo = DatabaseConnectionString.Utility.ShowForm();
                    if (Pub.dbinfo.IsValid == false)
                    {
                        MessageBox.Show("데이터 베이스 정보가 없습니다\n프로그램이 정상 작동하지 않을 수 있습니다", 
                                       "Alert", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    this.Visible = true;
                }));
            }
            
            Properties.Settings.Default["CS"] = Pub.dbinfo.ToString();
            Properties.Settings.Default["gwcs"] = Pub.dbinfo.ToString();
        }
        
        /// <summary>
        /// 포트 7979가 이미 사용중인지 체크하고 경고 표시
        /// </summary>
        private void CheckPort7979InUse()
        {
            try
            {
                // 현재 사용중인 TCP 포트 목록 가져오기
                IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
                TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
                IPEndPoint[] tcpListeners = ipGlobalProperties.GetActiveTcpListeners();

                // 포트 7979가 이미 사용중인지 확인
                bool port7979InUse = false;
                
                // TCP 연결 중에서 7979 포트 사용하는지 확인
                foreach (var tcpInfo in tcpConnInfoArray)
                {
                    if (tcpInfo.LocalEndPoint.Port == 7979)
                    {
                        port7979InUse = true;
                        break;
                    }
                }
                
                // TCP 리스너 중에서 7979 포트 사용하는지 확인
                if (!port7979InUse)
                {
                    foreach (var listener in tcpListeners)
                    {
                        if (listener.Port == 7979)
                        {
                            port7979InUse = true;
                            break;
                        }
                    }
                }

                // 포트가 이미 사용중이면 경고 메시지 표시
                if (port7979InUse)
                {
                    this.Invoke(new Action(() => {
                        string warningMessage = "⚠️ 경고: 포트 7979가 이미 사용 중입니다!\n\n" +
                                              "다른 프로그램이 포트 7979를 사용하고 있어서\n" +
                                              "웹 서버가 정상적으로 시작되지 않을 수 있습니다.\n\n" +
                                              "해결방법:\n" +
                                              "1. 다른 GroupWare 프로그램을 종료하세요\n" +
                                              "2. 작업관리자에서 관련 프로세스를 종료하세요\n" +
                                              "3. 컴퓨터를 재시작하세요";
                        
                        MessageBox.Show(warningMessage, "포트 충돌 경고", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }));
                    
                    FCOMMON.Pub.log.Add($"포트 7979가 이미 사용 중입니다. 웹서버 시작에 문제가 발생할 수 있습니다.");
                }
            }
            catch (Exception ex)
            {
                // 포트 체크 중 오류가 발생해도 프로그램 실행은 계속
                FCOMMON.Pub.log.AddE($"포트 7979 체크 중 오류 발생: {ex.Message}");
                Console.WriteLine($"Port check error: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 바코드 설정 초기화
        /// </summary>
        private void InitializeBarcodeSettings()
        {
            Pub.barcode = new Device.Barcode();
            if (!Pub.setting.Barcode.isEmpty()) 
                Pub.barcode.PortName = Pub.setting.Barcode;
            
            FCOMMON.info.camIndex = Pub.setting.CamIndex;
        }


        

        /// <summary>
        /// WebView2Runtime 압축해제 체크 및 실행
        /// </summary>
        private async Task CheckAndExtractWebView2Runtime()
        {
            var fi = new System.IO.FileInfo("WebView2Runtime.zip");
            if (!fi.Exists) return;

            var existlen = 0;
            var webruntimepath = new System.IO.DirectoryInfo("WebView2Runtime");
            if (webruntimepath.Exists)
            {
                var filen = new System.IO.FileInfo("WebView2Runtime\\version.txt");
                if (filen.Exists)
                {
                    var verstr = System.IO.File.ReadAllText(filen.FullName);
                    int.TryParse(verstr, out existlen);
                }
            }

            if (existlen != fi.Length)
            {
                this.Invoke(new Action(() => {
                    label1.Text = "📦 WebView2Runtime 압축해제 중...";
                }));

                await Task.Run(() => {
                    // fUnZip 폼을 메인 스레드에서 생성
                    fUnZip fprogress = null;
                    this.Invoke(new Action(() => {
                        fprogress = new fUnZip();
                        fprogress.TopMost = true;
                        fprogress.Show();
                        Application.DoEvents();
                    }));

                    try
                    {
                        if (webruntimepath.Exists)
                        {
                            this.Invoke(new Action(() => {
                                fprogress.label1.Text = "기존폴더삭제";
                                Application.DoEvents();
                            }));
                            webruntimepath.Delete(true);
                        }
                        
                        var diruntime = new System.IO.DirectoryInfo("runtimes");
                        if (diruntime.Exists) diruntime.Delete(true);
                        webruntimepath.Create();
                        diruntime.Create();

                        using (var archive = ZipFile.OpenRead(fi.FullName))
                        {
                            int totalFiles = archive.Entries.Count;
                            int currentFile = 0;
                            long totalSize = archive.Entries.Sum(e => e.Length);
                            long extractedSize = 0;

                            foreach (var entry in archive.Entries)
                            {
                                currentFile++;
                                extractedSize += entry.Length;
                                int progress = (int)((extractedSize * 100) / totalSize);

                                this.Invoke(new Action(() => {
                                    fprogress.label1.Text = $"압축 해제 중... ({currentFile}/{totalFiles})";
                                    fprogress.label2.Text = $"{entry.FullName} ({progress}%)";
                                    fprogress.progressBar1.Value = progress;
                                    Application.DoEvents();
                                }));

                                string destinationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, entry.FullName);
                                string destinationDir = Path.GetDirectoryName(destinationPath);

                                if (!Directory.Exists(destinationDir))
                                    Directory.CreateDirectory(destinationDir);

                                if (entry.Length > 0)
                                    entry.ExtractToFile(destinationPath, true);
                            }
                        }

                        System.IO.File.WriteAllText("WebView2Runtime\\version.txt", fi.Length.ToString());
                    }
                    catch (Exception ex)
                    {
                        this.Invoke(new Action(() => {
                            fprogress.Hide();
                            MessageBox.Show($"WebView2 Runtime 압축 해제 중 오류가 발생했습니다: {ex.Message}", 
                                           "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }));
                    }
                    finally
                    {
                        this.Invoke(new Action(() => {
                            fprogress.Dispose();
                        }));
                    }
                });
            }
        }
        
    }
}
