using Tiobon.Core.OPS.Tool.OPS.Tool.Helper;
using Tiobon.Core.OPS.Tool.OPS.Tool.Model;
using Tiobon.Core.OPS.Tool.OPS.Tool.View;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace Tiobon.Core.OPS.Tool.OPS.Tool.Src
{
    public class Module_method
    {
        #region 全局变量
        SSHHelper sSH = new SSHHelper(Const.config.ip, Const.config.ssh_port, Const.config.ssh_user, Const.config.ssh_passwd);
        SFTPHelper sFTP = new SFTPHelper(Const.config.ip, Const.config.ssh_port, Const.config.ssh_user, Const.config.ssh_passwd);
        bool isLinux = Const.config.system == "Linux";
        public Action End_Init;
        Module module_conf;
        #endregion

        #region 获取配置信息
        public Module GetConf(string filepath)
        {
            Const.ExtractSpecifyZipFile(filepath, "Config/", "", new List<string> { "README.ihdis" });
            string fm = File.ReadAllText("Config/README.ihdis");
            JavaScriptSerializer js = new JavaScriptSerializer();
            module_conf = js.Deserialize<Module>(fm);
            return module_conf;
        }
        #endregion

        #region 检测压缩包是否损坏
        public bool Is_BadZip(string path)
        {
            try
            {
                ZipFile entry = new ZipFile(path);
                return true;
            }
            catch
            {
                return false;
            }
        }
        #endregion

        #region 模块安装
        public void Install(string filepath, Action<string> handle)
        {
            bool isLinux = Const.config.system == "Linux";
            var hospital = Const.config.install_item_dir.Split('/').Last();
            if (isLinux)
            {
                var installpath = $"/home/{Const.config.ssh_user}/ihdis/tools/{module_conf.Name}";
                var webpath = $"/home/{Const.config.ssh_user}/ihdis/produse";
                try
                {
                    sSH.Connect();
                    var tmpdir = $"/tmp/{module_conf.Name}{new Random().Next(10000, 20000)}";
                    //1，上传文件
                    handle?.Invoke("正在上传文件...");
                    Upload(filepath, handle);

                    //2，解压到临时目录
                    handle?.Invoke("正在解压到临时目录...");
                    sSH.Excute_Longcmd($"unzip -qo /home/{Const.config.ssh_user}/ihdis/tools/{filepath.Split('\\')[filepath.Split('\\').Length - 1]} -d {tmpdir}");

                    if (File.Exists("Config/README.ihdis"))
                    {
                        sFTP.Connect();
                        sFTP.Put("Config/README.ihdis", $"{tmpdir}", "README.ihdis");
                        sFTP.Disconnect();
                    }

                    var tmp = Const.config.install_item_dir.Split('/');
                    var item = Const.MultiEnvs.Where(o => o.Ip == Const.config.ip && o.FileName == tmp[tmp.Length - 1]).FirstOrDefault();

                    //3，运行init.sh脚本
                    sSH.Excute_Longcmd_NoError($"cd {installpath} && sudo docker-compose down ");
                    sSH.Excute_Longcmd_NoError($"rm -rf {installpath}");
                    handle?.Invoke("运行init.sh脚本...");
                    sSH.Excute_Longcmd_NoError($"sudo sh {tmpdir}/init.sh {tmpdir} {installpath} {webpath}");
                    sSH.Excute_Longcmd($"sed -i \"s/JL_NETWORK=.*/JL_NETWORK={item.FileName}_oi_net/\" {installpath}/.env");

                    //4.启动docker
                    handle?.Invoke("启动插件...");
                    sSH.Excute_Longcmd_NoError($"cd {installpath} && sudo docker-compose up -d ");

                    // 5， 添加开机启动
                    handle?.Invoke("添加开机启动...");
                    PluginAutoRestart(installpath, module_conf.Name);

                    // 6，清理缓存
                    handle?.Invoke("清理缓存...");
                    sSH.Excute_Longcmd($"sudo bash -c 'echo 3 > /proc/sys/vm/drop_caches'");

                    //7.删除临时文件
                    sSH.Excute_Longcmd($"rm -r {tmpdir}");
                    var tmp1 = filepath.Split('\\');
                    string filename = tmp1[tmp1.Length - 1];
                    if (sFTP.Exists($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename))
                        sFTP.Delete($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename);

                    handle?.Invoke("安装完成...");
                    sSH.Disconnect();
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"安装过程出错，请截图错误信息或复制日志后联系工程师!\r\n\r\n{ex.Message}");
                }
            }
            else
            {
                #region Windows

                var tmpdir = $"{Path.GetTempPath()}{module_conf.Name}{new Random().Next(10000, 20000)}";

                //1.解压目录
                Const.write_task_log("正在解压安装包...");
                if (!Directory.Exists(tmpdir))
                    Directory.CreateDirectory(tmpdir);
                Const.ExtractZipFile(filepath, tmpdir, "", null);

                //2.创建安装目录
                var installpath = $"{Const.config.install_dir}\\tools\\{module_conf.Name}";
                if (!Directory.Exists(installpath))
                    Directory.CreateDirectory(installpath);

                //3.进行插件初始化
                handle?.Invoke("正在初始化插件...");
                Init(tmpdir, installpath, hospital, handle);
                Const.DeleteADirectory(tmpdir + "\\");
                handle?.Invoke("安装完成...");
                Thread.Sleep(2000);
                #endregion
            }
            End_Init();
        }
        #endregion

        #region 插件开机启动
        public void PluginAutoRestart(string installPath, string model)
        {
            try
            {
                sSH.Excute_Longcmd($"sudo cd {installPath}");
                sSH.Excute_Longcmd($"sudo echo '#!/bin/bash' > autostart_{model}.sh");
                sSH.Excute_Longcmd($"sudo echo '#chkconfig:345 95 95' >> autostart_{model}.sh");
                sSH.Excute_Longcmd($"sudo echo '#description:开机自启脚本' >> autostart_{model}.sh");
                sSH.Excute_Longcmd($"sudo echo 'cd {installPath}' >> autostart_{model}.sh");
                sSH.Excute_Longcmd($"sudo echo 'sudo docker-compose  restart' >> autostart_{model}.sh");

                sSH.Excute_Longcmd($"sudo mv autostart_{model}.sh   /etc/rc.d/init.d");
                sSH.Excute_Longcmd($"sudo chmod +x  /etc/rc.d/init.d/autostart_{model}.sh");
                sSH.Excute_Longcmd($"cd  /etc/rc.d/init.d");

                sSH.Excute_Longcmd($"sudo chkconfig  --add autostart_{model}.sh");
                //sSH.Excute_Longcmd($"chkconfig --list");

                sSH.Excute_Longcmd($"sudo chkconfig autostart_{model}.sh on");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"插件开机启动失败，请截图错误信息或复制日志后联系工程师!\r\n\r\n{ex.Message}");
            }
        }
        #endregion

        #region 上传文件
        public void Upload(string filepath, Action<string> handle)
        {
            try
            {
                var tmp = filepath.Split('\\');
                string filename = tmp[tmp.Length - 1];
                sFTP.Connect();
                if (sFTP.Exists($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename))
                {
                    handle?.Invoke($"删除同名更新包...");
                    sFTP.Delete($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename);
                    handle?.Invoke($"【{filename}】删除完成...");
                }
                handle?.Invoke($"开始上传更新包...");
                sFTP.Put(filepath, $"/home/{Const.config.ssh_user}/ihdis/tools/", filename);
                handle?.Invoke($"更新包上传完成...");
                sFTP.Disconnect();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"上传文件失败，请截图错误信息或复制日志后联系工程师!\r\n\r\n{ex.Message}");
            }
        }
        #endregion

        /// <summary>
        /// 初始化插件
        /// </summary>
        /// <param name="tmpdir"></param>
        /// <param name="installPath"></param>
        /// <param name="hospital"></param>
        public void Init(string tmpdir, string installPath, string hospital, Action<string> handle)
        {
            var allOldLines = new List<string>();
            if (File.Exists($"{installPath}\\.env"))
                allOldLines = File.ReadAllLines($"{installPath}\\.env").ToList<string>();

            Const.CopyDir(tmpdir, installPath);
            var env = File.ReadAllText($"{tmpdir}\\.env").ToLower();
            var tmp = Const.config.install_item_dir.Split('/');
            var item = Const.MultiEnvs.Where(o => o.Ip == Const.config.ip && o.FileName == tmp[tmp.Length - 1]).FirstOrDefault();

            // 判断安装插件类型
            if (env.Contains("ts"))
            {
                Const.CopyDir($"{installPath}\\conf", $"{installPath}\\code");
                CmdHelper.RunCmd($"docker load -i {installPath}\\ts.base.tar.gz\r\ndocker tag hh/ts:base hh/ts:1.33.0", out _);
            }
            else if (env.Contains("fsc"))
            {
                CmdHelper.RunCmd($"docker import {installPath}\\fsc.tar.gz hh/fsc:1.0.0", out _);
            }
            else if (env.Contains("hdis_qc")) // 质控插件
            {
                var allLines = File.ReadAllLines($"{tmpdir}\\.env").ToList<string>();

                var projectNameStr = "PROJECT_NAME=";
                var apiVersionStr = "API_VERSION=";
                var webVersionStr = "WEB_VERSION=";

                var projectName = allLines.Where(o => o.Contains(projectNameStr)).FirstOrDefault()?.Split('=')[1];
                var apiVersion = allLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1];
                var webVersion = allLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1];

                #region 删除旧镜像
                if (allOldLines.Any())
                {
                    handle?.Invoke("开始删除旧镜像...");
                    var projectName1 = allOldLines.Where(o => o.Contains(projectNameStr)).FirstOrDefault()?.Split('=')[1];
                    var apiVersion1 = allOldLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1];
                    var webVersion1 = allOldLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1];

                    CmdHelper.RunCmd($"docker rmi {projectName1}/api:{apiVersion1}", out _);
                    CmdHelper.RunCmd($"docker rmi {projectName1}/web:{webVersion1}", out _);
                    handle?.Invoke("完成删除旧镜像...");
                }
                #endregion

                handle?.Invoke("挂载镜像...");

                #region 替换端口号、子网掩码
                var newEnv = File.ReadAllText($"{tmpdir}\\.env").Replace("produce_oi_net", $"{item.FileName}_oi_net");
                File.WriteAllText($"{installPath}/.env", newEnv);

                var yml = File.ReadAllText($"{installPath}/docker-compose.yml");
                yml = yml.Replace("produce_oi_net", $"{item.FileName}_oi_net");
                File.WriteAllText($"{installPath}/docker-compose.yml", yml);

                #endregion

                //生成Docker Desktop挂载目录
                Main_method.AddDockerMountPath(yml, installPath);

                CmdHelper.RunCmd($"docker images --format \"{{{{.Repository}}}}:{{{{.Tag}}}}\"", out string res);
                if (!res.Contains($"{projectName}/api:{apiVersion}"))
                    CmdHelper.RunCmd($"docker load -i {installPath}\\images\\{projectName}_api_{apiVersion}.tar", out _);

                if (!res.Contains($"{projectName}/web:{apiVersion}"))
                    CmdHelper.RunCmd($"docker load -i {installPath}\\images\\{projectName}_web_{webVersion}.tar", out _);
                handle?.Invoke("挂载镜像完成...");
            }
            var resultLog = string.Empty;
            handle?.Invoke("正在启动容器...");
            CmdHelper.RunCmd($"{installPath.Split(':')[0].Trim()}: \r\ncd {$"{installPath}/"}" +
                    $"\r\ndocker-compose up -d \r\nexit", out resultLog);

            if (env.Contains("ts"))
            {
                var webPath = $"{Const.config.install_dir}\\{hospital}";
                var webConf = $"{webPath}\\conf\\nginx\\site\\web.conf";
                var webConfLines = File.ReadAllLines(webConf).ToList<string>();
                if (!webConfLines.Any(o => o.Contains("ts/ts")))
                {
                    webConfLines.Insert(6, "    location /ts/ {");
                    webConfLines.Insert(7, "         proxy_pass http://ts/ts/;");
                    webConfLines.Insert(8, "    }");
                    File.WriteAllLines(webConf, webConfLines);
                    handle?.Invoke("正在重启nginx...");
                    CmdHelper.RunCmd($"{webPath.Split(':')[0].Trim()}: \r\ncd {$"{webPath}/"}" +
                                 $"\r\ndocker-compose restart nginx \r\nexit", out _);
                }
            }
        }
    }
}
