using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Security;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;

namespace MesWork.Pages
{
    /// <summary>
    /// 系统设置页面 — 扫码枪连接管理
    /// </summary>
    public partial class UC_SystemSettings : UserControl
    {
        private const string AutoStartKeyName = "WC_GKJ_OIL";
        private const string AutoStartRunKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
        private const string AutoStartTaskName = "WC_GKJ_OIL_AutoStart";
        private bool _isLoadingAutoStart;
        private CheckBox chk_AutoStart;
        private Label lbl_AutoStartStatus;

        // 工位1控件
        private ComboBox cmb_Com1;
        private Button btn_Connect1, btn_Disconnect1, btn_ManualSend1;
        private Label lbl_Status1, lbl_ScanTime1;
        private TextBox txt_Barcode1;

        // 工位2控件
        private ComboBox cmb_Com2;
        private Button btn_Connect2, btn_Disconnect2, btn_ManualSend2;
        private Label lbl_Status2, lbl_ScanTime2;
        private TextBox txt_Barcode2;

        public UC_SystemSettings()
        {
            InitializeComponent();

            string station1 = MesWorkForm.Station1OpName;
            string station2 = MesWorkForm.Station2OpName;
            grp_Station1.Text = $"  工位1（{station1}）  ";
            grp_Station2.Text = $"  工位2（{station2}）  ";
            grp_Scanner1.Text = $"  {station1} 扫码枪  ";
            grp_Scanner2.Text = $"  {station2} 扫码枪  ";
            BuildAutoStartPanel();

            if (BarcodeManager.IsEnabled)
            {
                BuildScannerPanel(grp_Scanner1, station1, ref cmb_Com1, ref lbl_Status1, ref txt_Barcode1, ref lbl_ScanTime1,
                    ref btn_Connect1, ref btn_Disconnect1, ref btn_ManualSend1);
                BuildScannerPanel(grp_Scanner2, station2, ref cmb_Com2, ref lbl_Status2, ref txt_Barcode2, ref lbl_ScanTime2,
                    ref btn_Connect2, ref btn_Disconnect2, ref btn_ManualSend2);
                timer_Refresh.Start();
            }
            else
            {
                BuildScannerPanel(grp_Scanner1, station1, ref cmb_Com1, ref lbl_Status1, ref txt_Barcode1, ref lbl_ScanTime1,
                    ref btn_Connect1, ref btn_Disconnect1, ref btn_ManualSend1);
                BuildScannerPanel(grp_Scanner2, station2, ref cmb_Com2, ref lbl_Status2, ref txt_Barcode2, ref lbl_ScanTime2,
                    ref btn_Connect2, ref btn_Disconnect2, ref btn_ManualSend2);
                grp_Scanner1.Enabled = false;
                grp_Scanner2.Enabled = false;
            }
        }

        /// <summary>
        /// 构建开机自启设置区域，状态直接读取Windows当前用户启动项。
        /// </summary>
        private void BuildAutoStartPanel()
        {
            var grpAutoStart = new GroupBox
            {
                Text = "  开机自启  ",
                Font = new Font("微软雅黑", 12F, FontStyle.Bold),
                ForeColor = Color.FromArgb(30, 58, 95),
                Location = new Point(30, 410),
                Size = new Size(840, 120)
            };

            chk_AutoStart = new CheckBox
            {
                Text = "启用开机自启",
                Font = new Font("微软雅黑", 11F, FontStyle.Bold),
                ForeColor = Color.FromArgb(31, 41, 55),
                Location = new Point(24, 36),
                AutoSize = true,
                Cursor = Cursors.Hand
            };
            chk_AutoStart.CheckedChanged += chk_AutoStart_CheckedChanged;
            grpAutoStart.Controls.Add(chk_AutoStart);

            lbl_AutoStartStatus = new Label
            {
                Text = "--",
                Font = new Font("微软雅黑", 10F),
                ForeColor = Color.FromArgb(75, 85, 99),
                Location = new Point(24, 72),
                AutoSize = true
            };
            grpAutoStart.Controls.Add(lbl_AutoStartStatus);

            Controls.Add(grpAutoStart);
            RefreshAutoStartState();
        }

        /// <summary>
        /// 动态构建单个扫码枪面板的控件
        /// </summary>
        private void BuildScannerPanel(GroupBox grp, string opName,
            ref ComboBox cmb, ref Label lblStatus, ref TextBox txtBar, ref Label lblTime,
            ref Button btnConn, ref Button btnDisc, ref Button btnSend)
        {
            var normalFont = new Font("微软雅黑", 10F);
            var boldFont = new Font("微软雅黑", 10F, FontStyle.Bold);
            int y1 = 35, y2 = 75, y3 = 115;

            // Row 1: COM口选择 + 连接/断开
            var lblCom = new Label { Text = "COM口:", Font = normalFont, ForeColor = Color.FromArgb(55, 65, 81),
                Location = new Point(20, y1 + 4), AutoSize = true };
            grp.Controls.Add(lblCom);

            cmb = new ComboBox { Font = normalFont, Location = new Point(90, y1), Size = new Size(110, 28),
                DropDownStyle = ComboBoxStyle.DropDownList };
            RefreshComPorts(cmb, opName);
            grp.Controls.Add(cmb);

            // 局部变量捕获（ref参数不能在lambda中使用）
            var localCmb = cmb;
            var localTxtBar = txtBar;

            btnConn = new Button
            {
                Text = "🔗 连接", Font = boldFont, Size = new Size(90, 30), Location = new Point(215, y1 - 2),
                BackColor = Color.FromArgb(74, 144, 217), ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat, Cursor = Cursors.Hand
            };
            btnConn.FlatAppearance.BorderSize = 0;
            btnConn.Click += (s, e) => DoConnect(opName, localCmb);
            grp.Controls.Add(btnConn);

            btnDisc = new Button
            {
                Text = "⛔ 断开", Font = boldFont, Size = new Size(90, 30), Location = new Point(315, y1 - 2),
                BackColor = Color.FromArgb(239, 68, 68), ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat, Cursor = Cursors.Hand
            };
            btnDisc.FlatAppearance.BorderSize = 0;
            btnDisc.Click += (s, e) => DoDisconnect(opName);
            grp.Controls.Add(btnDisc);

            // 刷新COM口列表按钮
            var btnRefresh = new Button
            {
                Text = "🔄", Font = normalFont, Size = new Size(36, 30), Location = new Point(415, y1 - 2),
                FlatStyle = FlatStyle.Flat, Cursor = Cursors.Hand,
                BackColor = Color.FromArgb(229, 231, 235)
            };
            btnRefresh.FlatAppearance.BorderSize = 0;
            btnRefresh.Click += (s, e) => RefreshComPorts(localCmb, opName);
            grp.Controls.Add(btnRefresh);

            lblStatus = new Label { Text = "● 未连接", Font = boldFont, ForeColor = Color.FromArgb(156, 163, 175),
                Location = new Point(470, y1 + 4), AutoSize = true };
            grp.Controls.Add(lblStatus);

            // Row 2: 最近码值 + 手动发送
            var lblBar = new Label { Text = "码值:", Font = normalFont, ForeColor = Color.FromArgb(55, 65, 81),
                Location = new Point(20, y2 + 4), AutoSize = true };
            grp.Controls.Add(lblBar);

            txtBar = new TextBox { Font = normalFont, Location = new Point(90, y2), Size = new Size(300, 28),
                BorderStyle = BorderStyle.FixedSingle };
            localTxtBar = txtBar; // 更新局部变量
            grp.Controls.Add(txtBar);

            btnSend = new Button
            {
                Text = "📤 手动发送", Font = boldFont, Size = new Size(120, 30), Location = new Point(405, y2 - 2),
                BackColor = Color.FromArgb(5, 150, 105), ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat, Cursor = Cursors.Hand
            };
            btnSend.FlatAppearance.BorderSize = 0;
            btnSend.Click += (s, e) => DoManualSend(opName, localTxtBar);
            grp.Controls.Add(btnSend);

            // Row 3: 扫码时间
            var lblTimeLbl = new Label { Text = "扫码时间:", Font = normalFont, ForeColor = Color.FromArgb(55, 65, 81),
                Location = new Point(20, y3 + 4), AutoSize = true };
            grp.Controls.Add(lblTimeLbl);

            lblTime = new Label { Text = "--", Font = normalFont, ForeColor = Color.FromArgb(31, 41, 55),
                Location = new Point(110, y3 + 4), AutoSize = true };
            grp.Controls.Add(lblTime);
        }

        // ── 操作方法 ──

        private string GetAutoStartCommand()
        {
            return Application.ExecutablePath;
        }

        private bool RunSchtasks(string arguments, out string output)
        {
            output = "";
            try
            {
                var psi = new ProcessStartInfo
                {
                    FileName = "schtasks.exe",
                    Arguments = arguments,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };
                using (Process process = Process.Start(psi))
                {
                    output = process.StandardOutput.ReadToEnd() + process.StandardError.ReadToEnd();
                    process.WaitForExit();
                    return process.ExitCode == 0;
                }
            }
            catch (Exception ex)
            {
                output = ex.Message;
                return false;
            }
        }

        private bool TryGetAutoStartTaskXml(out string taskXml, out string errMsg)
        {
            taskXml = "";
            errMsg = "";
            if (RunSchtasks($"/Query /TN \"{AutoStartTaskName}\" /XML", out string output))
            {
                taskXml = output;
                return true;
            }

            if (IsTaskNotFoundOutput(output))
            {
                return true;
            }

            errMsg = output;
            return false;
        }

        private bool IsTaskNotFoundOutput(string output)
        {
            return output.IndexOf("cannot find", StringComparison.OrdinalIgnoreCase) >= 0 ||
                output.Contains("找不到") ||
                output.Contains("不存在");
        }

        private void DeleteLegacyRegistryAutoStart()
        {
            try
            {
                using (RegistryKey key = Registry.CurrentUser.OpenSubKey(AutoStartRunKeyPath, true))
                {
                    key?.DeleteValue(AutoStartKeyName, false);
                }
            }
            catch
            {
            }
        }

        private bool TryCreateAutoStartTask(out string errMsg)
        {
            errMsg = "";
            string xmlPath = Path.Combine(Path.GetTempPath(), $"{AutoStartTaskName}.xml");
            string exePath = GetAutoStartCommand();
            string workDir = Path.GetDirectoryName(exePath);
            string taskXml =
$@"<?xml version=""1.0"" encoding=""UTF-16""?>
<Task version=""1.2"" xmlns=""http://schemas.microsoft.com/windows/2004/02/mit/task"">
  <RegistrationInfo>
    <Description>潍柴称重工控机程序开机自启</Description>
  </RegistrationInfo>
  <Triggers>
    <LogonTrigger>
      <Enabled>true</Enabled>
      <Delay>PT30S</Delay>
    </LogonTrigger>
  </Triggers>
  <Principals>
    <Principal id=""Author"">
      <LogonType>InteractiveToken</LogonType>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>false</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context=""Author"">
    <Exec>
      <Command>{SecurityElement.Escape(exePath)}</Command>
      <WorkingDirectory>{SecurityElement.Escape(workDir)}</WorkingDirectory>
    </Exec>
  </Actions>
</Task>";

            try
            {
                File.WriteAllText(xmlPath, taskXml, System.Text.Encoding.Unicode);
                if (RunSchtasks($"/Create /TN \"{AutoStartTaskName}\" /XML \"{xmlPath}\" /F", out string output))
                {
                    DeleteLegacyRegistryAutoStart();
                    return true;
                }
                errMsg = output;
                return false;
            }
            catch (Exception ex)
            {
                errMsg = ex.Message;
                return false;
            }
            finally
            {
                try { if (File.Exists(xmlPath)) File.Delete(xmlPath); } catch { }
            }
        }

        private bool IsCurrentProgramAutoStart(string taskXml)
        {
            return !string.IsNullOrWhiteSpace(taskXml) &&
                taskXml.IndexOf(GetAutoStartCommand(), StringComparison.OrdinalIgnoreCase) >= 0;
        }

        private bool TrySetAutoStart(bool enabled, out string errMsg)
        {
            errMsg = "";
            if (enabled)
            {
                return TryCreateAutoStartTask(out errMsg);
            }

            DeleteLegacyRegistryAutoStart();
            if (RunSchtasks($"/Delete /TN \"{AutoStartTaskName}\" /F", out string output))
            {
                return true;
            }

            if (IsTaskNotFoundOutput(output))
            {
                return true;
            }

            errMsg = output;
            return false;
        }

        private void RefreshAutoStartState()
        {
            if (chk_AutoStart == null || lbl_AutoStartStatus == null) return;

            _isLoadingAutoStart = true;
            try
            {
                if (!TryGetAutoStartTaskXml(out string taskXml, out string errMsg))
                {
                    chk_AutoStart.Checked = false;
                    lbl_AutoStartStatus.Text = $"读取任务计划失败：{errMsg}";
                    lbl_AutoStartStatus.ForeColor = Color.FromArgb(239, 68, 68);
                    return;
                }

                bool isCurrentProgramAutoStart = IsCurrentProgramAutoStart(taskXml);
                chk_AutoStart.Checked = isCurrentProgramAutoStart;
                if (isCurrentProgramAutoStart)
                {
                    lbl_AutoStartStatus.Text = $"已启用任务计划：{Application.ExecutablePath}";
                    lbl_AutoStartStatus.ForeColor = Color.FromArgb(16, 185, 129);
                }
                else if (string.IsNullOrWhiteSpace(taskXml))
                {
                    lbl_AutoStartStatus.Text = "未启用";
                    lbl_AutoStartStatus.ForeColor = Color.FromArgb(107, 114, 128);
                }
                else
                {
                    lbl_AutoStartStatus.Text = "任务计划存在但路径不是当前程序，请重新勾选修正";
                    lbl_AutoStartStatus.ForeColor = Color.FromArgb(245, 158, 11);
                }
            }
            finally
            {
                _isLoadingAutoStart = false;
            }
        }

        private void chk_AutoStart_CheckedChanged(object sender, EventArgs e)
        {
            if (_isLoadingAutoStart) return;

            bool enabled = chk_AutoStart.Checked;
            if (!TrySetAutoStart(enabled, out string errMsg))
            {
                MessageBox.Show($"开机自启设置失败：{errMsg}", "设置失败", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            RefreshAutoStartState();
        }

        private void DoConnect(string opName, ComboBox cmb)
        {
            string com = cmb.SelectedItem?.ToString();
            if (string.IsNullOrEmpty(com))
            {
                MessageBox.Show("请选择COM口", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            BarcodeScanner scanner;
            if (!BarcodeManager.Scanners.TryGetValue(opName, out scanner))
            {
                scanner = new BarcodeScanner(opName, MesWorkForm.BarcodeBaudRate);
                scanner.BarcodeReceived += (op, code) => BarcodeManager.ManualSend(op, code);
                BarcodeManager.Scanners[opName] = scanner;
            }

            bool ok = scanner.Connect(com);
            MessageBox.Show(ok ? $"{opName} 扫码枪已连接 ({com})" : $"{opName} 连接失败，请检查COM口",
                "连接结果", MessageBoxButtons.OK, ok ? MessageBoxIcon.Information : MessageBoxIcon.Warning);
        }

        private void DoDisconnect(string opName)
        {
            if (BarcodeManager.Scanners.TryGetValue(opName, out var scanner))
            {
                scanner.Disconnect();
                MessageBox.Show($"{opName} 扫码枪已断开", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void DoManualSend(string opName, TextBox txtBar)
        {
            string barcode = txtBar.Text.Trim();
            if (string.IsNullOrEmpty(barcode))
            {
                MessageBox.Show("请输入条码值", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            BarcodeManager.ManualSend(opName, barcode);
            MessageBox.Show($"已手动发送条码：{barcode}\n工位：{opName}", "发送成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private async void btn_WeightClear1_Click(object sender, EventArgs e)
        {
            await DoWeightClearAsync(MesWorkForm.Station1OpName, btn_WeightClear1);
        }

        private async void btn_WeightClear2_Click(object sender, EventArgs e)
        {
            await DoWeightClearAsync(MesWorkForm.Station2OpName, btn_WeightClear2);
        }

        private async Task DoWeightClearAsync(string opName, Button btn)
        {
            try
            {
                btn.Enabled = false;
                MesWorkForm.WritePLC_IF(100017, opName, 1);
                await Task.Delay(1000);
                MesWorkForm.WritePLC_IF(100017, opName, 0);
                MessageBox.Show($"{opName} 称重清零信号已发送", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MesWorkForm.WriteLog_Info("系统设置", $"{opName} 称重清零失败：{ex.Message}", ex);
                MessageBox.Show($"{opName} 称重清零失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                btn.Enabled = true;
            }
        }

        private void RefreshComPorts(ComboBox cmb, string opName)
        {
            cmb.Items.Clear();
            var ports = BarcodeManager.GetAvailablePorts();
            foreach (var p in ports)
                cmb.Items.Add(p);

            // 自动选中当前配置的COM口或已连接的COM口
            if (BarcodeManager.Scanners.TryGetValue(opName, out var scanner) && !string.IsNullOrEmpty(scanner.ComPort))
            {
                int idx = cmb.Items.IndexOf(scanner.ComPort);
                if (idx >= 0) cmb.SelectedIndex = idx;
            }
        }

        // ── 定时刷新状态 ──

        private void timer_Refresh_Tick(object sender, EventArgs e)
        {
            RefreshScannerStatus(MesWorkForm.Station1OpName, lbl_Status1, txt_Barcode1, lbl_ScanTime1);
            RefreshScannerStatus(MesWorkForm.Station2OpName, lbl_Status2, txt_Barcode2, lbl_ScanTime2);
        }

        private void RefreshScannerStatus(string opName, Label lblStatus, TextBox txtBar, Label lblTime)
        {
            if (lblStatus == null) return;

            if (BarcodeManager.Scanners.TryGetValue(opName, out var scanner))
            {
                if (scanner.IsConnected)
                {
                    lblStatus.Text = $"● 已连接 ({scanner.ComPort})";
                    lblStatus.ForeColor = Color.FromArgb(16, 185, 129); // 绿色
                }
                else
                {
                    lblStatus.Text = $"● 未连接 ({scanner.ComPort})";
                    lblStatus.ForeColor = Color.FromArgb(239, 68, 68); // 红色
                }

                // 仅在有新扫码时更新（避免覆盖用户手动输入）
                if (!string.IsNullOrEmpty(scanner.LastBarcode) && txtBar.Text != scanner.LastBarcode && !txtBar.Focused)
                    txtBar.Text = scanner.LastBarcode;

                lblTime.Text = scanner.LastScanTime.HasValue
                    ? scanner.LastScanTime.Value.ToString("yyyy-MM-dd HH:mm:ss")
                    : "--";
            }
            else
            {
                lblStatus.Text = "● 未配置";
                lblStatus.ForeColor = Color.FromArgb(156, 163, 175);
                lblTime.Text = "--";
            }
        }
    }
}
