using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using Newtonsoft.Json;
using System.Security.Cryptography;
using System.Net.Http;
using Microsoft.Win32;
using System.Security.Policy;
using System.Runtime.InteropServices;

namespace StudioClient
{
    public partial class Form1 : Form
    {
        static string serverUrl = "http://xr.flexing.ai:3030/XR_Server/";

        static string appName_Studio = "Studio";
        static string appName_StudioTwin = "StudioTwin";
        static string appName_StudioSimulator = "StudioSimulator";

        static string setupFileTag = "Setup.exe";

        static readonly HttpClient httpClient = new HttpClient();

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern uint RegisterWindowMessage(string lpString);

        private uint installCompleteMsg;
        private uint uninstallCompleteMsg;

        public Form1()
        {
            InitializeComponent();

            Initialize();
        }

        void Initialize()
        {
            installCompleteMsg = RegisterWindowMessage($@"INSTALL_COMPLETE");
            uninstallCompleteMsg = RegisterWindowMessage($@"UNINSTALL_COMPLETE");

            string installPath;

            installPath = GetInstalledPathFromRegistry(appName_Studio);
            if (!string.IsNullOrWhiteSpace(installPath) && Directory.Exists(installPath))
            {
                SetButtonState(true, StudioInstallButton, StudioCheckButton, StudioDeleteButton);
            }
            else
            {
                SetButtonState(false, StudioInstallButton, StudioCheckButton, StudioDeleteButton);
            }
        }

        void SetButtonState(bool isInstallComplete, Button installButton, Button checkButton, Button deleteButton)
        {
            if (isInstallComplete)
            {
                installButton.Text = "실행";
                checkButton.Visible = true;
                checkButton.Enabled = true;
                deleteButton.Visible = true;
                deleteButton.Enabled = true;
            }
            else
            {
                installButton.Text = "설치";
                checkButton.Visible = false;
                checkButton.Enabled = false;
                deleteButton.Visible = false;
                deleteButton.Enabled = false;
            }
        } 

        private async void StudioInstallButton_Click(object sender, EventArgs e)
        {
            await OnClickButton(appName_Studio);
        }

        private async void StudioTwinInstallButton_Click(object sender, EventArgs e)
        {
            //await InstallApp(serverUrl, appName_StudioTwin);
        }

        private async void StudioSimulatorInstallButton_Click(object sender, EventArgs e)
        {

        }

        private async void StudioCheckButton_Click(object sender, EventArgs e)
        {
            
        }

        private async void StudioDeleteButton_Click(object sender, EventArgs e)
        {
            await UninstallApp(appName_Studio);
        }

        private async void StudioTwinDeleteButton_Click(object sender, EventArgs e)
        {

        }

        private async void StudioSimulatorDeleteButton_Click(object sender, EventArgs e)
        {

        }

        private async void WriteText(string text)
        {
            label1.Text = text;
        }

        private async Task OnClickButton(string appName)
        {
            string appUrl = Path.Combine(serverUrl, appName);

            // 이미 Setup으로 설치를 진행했는지 체크
            string installPath = GetInstalledPathFromRegistry(appName);
            string exeFilePath;

            if (!string.IsNullOrWhiteSpace(installPath) && Directory.Exists(installPath)) // 이미 설치 되있으면 경로에서 exe파일 실행
            {
                WriteText("런처 실행");

                exeFilePath = Directory.GetFiles(installPath, "*.exe", SearchOption.TopDirectoryOnly)
                    .FirstOrDefault(file =>
                        !Path.GetFileName(file).Equals("unins000.exe", StringComparison.OrdinalIgnoreCase) &&
                        Path.GetFileName(file).IndexOf("Launcher", StringComparison.OrdinalIgnoreCase) >= 0);


                if (string.IsNullOrEmpty(exeFilePath))
                {
                    WriteText("❌ 설치 경로에 실행할 수 있는 런처의 exe 파일이 없습니다.");
                    return;
                }

                StartExecutableFile(exeFilePath, installPath);
            }
            else // 설치 안되있으면 Setup 다운받고 Setup 실행
            {
                WriteText("설치 진행중");

                // Setup 파일이 이미 있으면 삭제하고 서버에서 새로 다운로드
                string setupFileName = appName + setupFileTag;
                if (File.Exists(setupFileName))
                {
                    File.Delete(setupFileName);
                }
                string setupFileUrl = Path.Combine(appUrl, setupFileName);
                await DownloadFile(setupFileUrl, ProgressBar);

                string currentDir = AppContext.BaseDirectory;
                exeFilePath = Path.Combine(currentDir, setupFileName);
                StartExecutableFile(exeFilePath, currentDir);
            }
        }

        private string GetInstalledPathFromRegistry(string appName)
        {
            try
            {
                using (RegistryKey key = Registry.CurrentUser.OpenSubKey($@"Software\UVC\{appName}"))
                {
                    if (key != null)
                    {
                        return key.GetValue("InstallPath") as string ?? "";
                    }
                }
            }
            catch (Exception ex)
            {
                WriteText($"❌ 레지스트리 읽기 실패 ({appName}): {ex.Message}");
            }

            return "";
        }

        private async Task DownloadFile(string url, ProgressBar progressBar)
        {
            try
            {
                string currentDir = AppContext.BaseDirectory;
                string fileName = Path.GetFileName(new Uri(url).LocalPath);
                string fullPath = Path.Combine(currentDir, fileName);

                using (var response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
                {
                    response.EnsureSuccessStatusCode();

                    long? totalBytes = response.Content.Headers.ContentLength;
                    if (totalBytes == null)
                    {
                        WriteText("❌ 파일 크기를 알 수 없습니다.");
                        return;
                    }

                    using (var contentStream = await response.Content.ReadAsStreamAsync())
                    using (var fileStream = new FileStream(fullPath, FileMode.Create, FileAccess.Write, FileShare.None))
                    {
                        progressBar.Invoke((MethodInvoker)(() =>
                        {
                            progressBar.Minimum = 0;
                            progressBar.Maximum = 100;
                            progressBar.Value = 0;
                        }));

                        byte[] buffer = new byte[81920]; // 80KB 버퍼
                        long totalRead = 0;
                        int bytesRead;

                        while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                        {
                            await fileStream.WriteAsync(buffer, 0, bytesRead);
                            totalRead += bytesRead;

                            int progress = (int)((totalRead * 100) / totalBytes.Value);

                            progressBar.Invoke((MethodInvoker)(() =>
                            {
                                progressBar.Value = Math.Min(progress, 100);
                            }));
                        }

                        WriteText("✅ 다운로드 완료!");
                    }
                }
            }
            catch (Exception ex)
            {
                WriteText($"❌ 다운로드 실패: {ex.Message}");
            }
        }


        private void StartExecutableFile(string exeFilePath, string workingDirectory)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                FileName = exeFilePath,
                WorkingDirectory = workingDirectory,
                UseShellExecute = true // Windows에서 기본 프로그램으로 실행
            };

            Process.Start(startInfo);
        }

        private async Task UninstallApp(string appName)
        {
            string appUrl = Path.Combine(serverUrl, appName);

                  // 설치가 이미 되어있는지 체크
            string installPath = GetInstalledPathFromRegistry(appName);
            string exeFilePath;

            if (!string.IsNullOrWhiteSpace(installPath) && Directory.Exists(installPath)) // 설치 되있으면 경로에서 Uninstaller 실행
            {
                exeFilePath = Directory.GetFiles(installPath, "unins000.exe", SearchOption.TopDirectoryOnly).FirstOrDefault();

                if (string.IsNullOrEmpty(exeFilePath))
                {
                    WriteText("❌ 설치 경로에 실행할 수 있는 unins000.exe 파일이 없습니다.");
                    return;
                }

                WriteText("Uninstaller 실행");

                StartExecutableFile(exeFilePath, installPath);
            }
            else
            {
                WriteText("❌ 설치된 경로가 없습니다.");
            }
        }

        // Install / Uninstall 완료 시
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == installCompleteMsg)
            {
                SetButtonState(true, StudioInstallButton, StudioCheckButton, StudioDeleteButton);
            }
            else if (m.Msg == uninstallCompleteMsg)
            {
                SetButtonState(false, StudioInstallButton, StudioCheckButton, StudioDeleteButton);
            }

            base.WndProc(ref m);
        }
    }
}
