using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CycleGUI;
using StandardScene.Utils;

namespace StandardScene.ExtendDevice.Door
{
    /// <summary>
    /// 门控制器配置管理（CycleGUI 版，替代原 WinForms <c>DoorManager</c> 窗体）。
    /// </summary>
    public class DoorManager
    {
        private const string DataFileName = "DoorConfig.json";
        private static string DataFilePath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DataFileName);
        private static readonly object SaveLock = new object();

        private static Panel _panel;
        private static List<DoorControllerModel> _controllers = new List<DoorControllerModel>();
        private static int _selectedCtrlIdx = -1;
        private static int _selectedDoorIdx = -1;
        private static string _status = "";

        private static string _ctrlIp = "";
        private static string _ctrlPort = "502";
        private static string _ctrlIndex = "";
        private static int _typeIdx;
        private static string[] _typeNames = Array.Empty<string>();

        private static string _doorIndex = "";
        private static string _doorCtrlAddr = "";
        private static string _doorOpenAddr = "";
        private static bool _doorNoControl;

        public static void OpenViewer() => Open();

        public static void Open()
        {
            if (_panel != null)
            {
                try { _panel.BringToFront(); return; }
                catch { _panel = null; }
            }

            _typeNames = DiscoverTypes();
            LoadData();
            _selectedCtrlIdx = -1;
            _selectedDoorIdx = -1;
            ClearControllerFields();
            ClearDoorFields();

            var panel = GUI.DeclarePanel()
                .ShowTitle("门控制器管理")
                .SetDefaultDocking(Panel.Docking.None)
                .InitSize(1100, 720)
                .InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
            _panel = panel;
            panel.IfTerminalQuit(() => { if (_panel == panel) _panel = null; });

            panel.Define(pb =>
            {
                if (pb.Closing())
                {
                    SaveData();
                    panel.Exit();
                    _panel = null;
                    return;
                }

                pb.SeparatorText("门控制器");
                pb.Table("door-ctrl-list", new[] { "控制器编码", "IP", "端口", "类型", "Ctrl操作" },
                    _controllers.Count, (row, i) =>
                    {
                        var c = _controllers[i];
                        row.Label($"{c.Index}");
                        row.Label(c.Ip);
                        row.Label($"{c.Port}");
                        row.Label(c.Type);
                        if (row.ButtonGroup(new[] { "选控制器" }, new[] { "选择该控制器" }) == 0)
                        {
                            _selectedCtrlIdx = i;
                            _selectedDoorIdx = -1;
                            LoadControllerFields(c);
                            ClearDoorFields();
                        }
                    }, height: 8, enableSearch: true);

                pb.SeparatorText("控制器编辑");
                var (ip, _) = pb.TextInput("1. IP", _ctrlIp, alwaysReturnString: true);
                _ctrlIp = ip;
                pb.SameLine(12);
                var (port, _) = pb.TextInput("2. 端口", _ctrlPort, alwaysReturnString: true);
                _ctrlPort = port;
                var (idx, _) = pb.TextInput("3. 控制器编码", _ctrlIndex, alwaysReturnString: true);
                _ctrlIndex = idx;
                if (_typeNames.Length > 0)
                    pb.DropdownBox("4. 类型", _typeNames, ref _typeIdx);

                if (pb.Button("添加控制器", distinct: "door-add-ctrl")) AddController();
                pb.SameLine(8);
                if (pb.Button("保存控制器", distinct: "door-save-ctrl")) SaveController();
                pb.SameLine(8);
                if (pb.Button("删除控制器", distinct: "door-del-ctrl")) ConfirmDeleteController();

                var doors = GetSelectedController()?.Doors ?? new List<DoorModel>();
                pb.SeparatorText($"门列表（控制器 #{GetSelectedController()?.Index ?? 0}，共 {doors.Count} 扇）");
                pb.Table("door-list", new[] { "门编码", "控制地址", "开到位地址", "无控制", "门操作" },
                    doors.Count, (row, i) =>
                    {
                        var d = doors[i];
                        row.Label($"{d.Index}");
                        row.Label($"{d.ControlAddress}");
                        row.Label($"{d.OpenStatusAddress}");
                        row.Label(d.NoControl ? "是" : "否");
                        if (row.ButtonGroup(new[] { "选门" }, new[] { "选择该门" }) == 0)
                        {
                            _selectedDoorIdx = i;
                            LoadDoorFields(d);
                        }
                    }, height: 6, enableSearch: true);

                pb.SeparatorText("门编辑");
                var (dIdx, _) = pb.TextInput("5. 门编码", _doorIndex, alwaysReturnString: true);
                _doorIndex = dIdx;
                var (cAddr, _) = pb.TextInput("6. 控制地址", _doorCtrlAddr, alwaysReturnString: true);
                _doorCtrlAddr = cAddr;
                var (oAddr, _) = pb.TextInput("7. 开到位地址", _doorOpenAddr, alwaysReturnString: true);
                _doorOpenAddr = oAddr;
                pb.CheckBox("8. 无控制", ref _doorNoControl);

                if (pb.Button("添加门", distinct: "door-add")) AddDoor();
                pb.SameLine(8);
                if (pb.Button("保存门", distinct: "door-save")) SaveDoor();
                pb.SameLine(8);
                if (pb.Button("删除门", distinct: "door-del")) ConfirmDeleteDoor();

                if (!string.IsNullOrEmpty(_status))
                {
                    pb.Separator();
                    pb.Label(_status);
                }
            });
        }

        private static DoorControllerModel GetSelectedController() =>
            _selectedCtrlIdx >= 0 && _selectedCtrlIdx < _controllers.Count ? _controllers[_selectedCtrlIdx] : null;

        private static DoorModel GetSelectedDoor()
        {
            var ctrl = GetSelectedController();
            return ctrl != null && _selectedDoorIdx >= 0 && _selectedDoorIdx < ctrl.Doors.Count
                ? ctrl.Doors[_selectedDoorIdx] : null;
        }

        private static string[] DiscoverTypes()
        {
            try
            {
                var names = SimpleLite.Utils.UiTypeDiscovery.AllTypes()
                    .Where(t => t.IsClass && !t.IsAbstract
                        && t.Namespace == typeof(BasicDoorController).Namespace
                        && t.IsSubclassOf(typeof(BasicDoorController))
                        && t.IsDefined(typeof(DoorTypeAttribute), false))
                    .Select(t => t.GetCustomAttribute<DoorTypeAttribute>()?.Name)
                    .Where(n => !string.IsNullOrWhiteSpace(n))
                    .OrderBy(n => n)
                    .ToArray();
                return names.Length > 0 ? names : new[] { "ModbusDoorController" };
            }
            catch
            {
                return new[] { "ModbusDoorController" };
            }
        }

        private static void LoadData()
        {
            try
            {
                if (!File.Exists(DataFilePath)) { _controllers = new List<DoorControllerModel>(); return; }
                var json = File.ReadAllText(DataFilePath, Encoding.UTF8);
                _controllers = string.IsNullOrWhiteSpace(json)
                    ? new List<DoorControllerModel>()
                    : json.JsonTo<List<DoorControllerModel>>() ?? new List<DoorControllerModel>();
            }
            catch (Exception ex)
            {
                _controllers = new List<DoorControllerModel>();
                _status = $"加载失败: {ex.Message}";
            }
        }

        private static void SaveData()
        {
            var json = _controllers.ToJson();
            var path = DataFilePath;
            Task.Run(() =>
            {
                try
                {
                    lock (SaveLock)
                        File.WriteAllText(path, json, Encoding.UTF8);
                }
                catch (Exception ex)
                {
                    _status = $"保存失败: {ex.Message}";
                    _panel?.Repaint();
                }
            });
        }

        private static void LoadControllerFields(DoorControllerModel c)
        {
            _ctrlIp = c.Ip;
            _ctrlPort = c.Port.ToString();
            _ctrlIndex = c.Index.ToString();
            _typeIdx = Math.Max(0, Array.IndexOf(_typeNames, c.Type));
            if (_typeIdx < 0) _typeIdx = 0;
        }

        private static void ClearControllerFields()
        {
            _ctrlIp = "";
            _ctrlPort = "502";
            _ctrlIndex = "";
            _typeIdx = 0;
        }

        private static void LoadDoorFields(DoorModel d)
        {
            _doorIndex = d.Index.ToString();
            _doorCtrlAddr = d.ControlAddress.ToString();
            _doorOpenAddr = d.OpenStatusAddress.ToString();
            _doorNoControl = d.NoControl;
        }

        private static void ClearDoorFields()
        {
            _doorIndex = "";
            _doorCtrlAddr = "";
            _doorOpenAddr = "";
            _doorNoControl = false;
        }

        private static void AddController()
        {
            if (!TryParseControllerInput(out var index, out var ip, out var port, out var type, false, out var err))
            {
                CycleUiHelper.Alert("错误", err);
                return;
            }
            if (_controllers.Any(c => c.Index == index)) { CycleUiHelper.Alert("错误", $"编码 {index} 已存在"); return; }
            if (_controllers.Any(c => c.Ip == ip)) { CycleUiHelper.Alert("错误", $"IP {ip} 已存在"); return; }

            var c = new DoorControllerModel { Index = index, Ip = ip, Port = port, Type = type };
            _controllers.Add(c);
            _selectedCtrlIdx = _controllers.Count - 1;
            SaveData();
            _status = "已添加门控制器";
            _panel?.Repaint();
        }

        private static void SaveController()
        {
            var cur = GetSelectedController();
            if (cur == null) { CycleUiHelper.Alert("提示", "请先选择要保存的门控制器"); return; }
            if (!TryParseControllerInput(out var index, out var ip, out var port, out var type, true, out var err))
            {
                CycleUiHelper.Alert("错误", err);
                return;
            }
            if (_controllers.Any(c => c.Index == index && c != cur)) { CycleUiHelper.Alert("错误", $"编码 {index} 已存在"); return; }
            if (_controllers.Any(c => c.Ip == ip && c != cur)) { CycleUiHelper.Alert("错误", $"IP {ip} 已存在"); return; }

            cur.Index = index;
            cur.Ip = ip;
            cur.Port = port;
            cur.Type = type;
            SaveData();
            _status = "门控制器已保存";
            CycleUiHelper.Alert("提示", "保存成功");
            _panel?.Repaint();
        }

        private static void ConfirmDeleteController()
        {
            var cur = GetSelectedController();
            if (cur == null) { CycleUiHelper.Alert("提示", "请选择要删除的门控制器"); return; }
            CycleUiHelper.ConfirmThen($"删除编码为 {cur.Index} 的门控制器？", () =>
            {
                _controllers.Remove(cur);
                _selectedCtrlIdx = -1;
                _selectedDoorIdx = -1;
                ClearControllerFields();
                ClearDoorFields();
                SaveData();
                _status = "已删除门控制器";
                _panel?.Repaint();
            });
        }

        private static void AddDoor()
        {
            var ctrl = GetSelectedController();
            if (ctrl == null) { CycleUiHelper.Alert("提示", "请先选择门控制器"); return; }
            if (!TryParseDoorInput(out var index, out var cAddr, out var oAddr, false, out var err))
            {
                CycleUiHelper.Alert("错误", err);
                return;
            }
            if (ctrl.Doors.Any(d => d.Index == index)) { CycleUiHelper.Alert("错误", $"门编码 {index} 已存在"); return; }

            var door = new DoorModel
            {
                Index = index,
                ControlAddress = cAddr,
                OpenStatusAddress = oAddr,
                NoControl = _doorNoControl
            };
            ctrl.Doors.Add(door);
            _selectedDoorIdx = ctrl.Doors.Count - 1;
            SaveData();
            _status = "已添加门";
            _panel?.Repaint();
        }

        private static void SaveDoor()
        {
            var ctrl = GetSelectedController();
            var door = GetSelectedDoor();
            if (ctrl == null || door == null) { CycleUiHelper.Alert("提示", "请先选择要保存的门"); return; }
            if (!TryParseDoorInput(out var index, out var cAddr, out var oAddr, true, out var err))
            {
                CycleUiHelper.Alert("错误", err);
                return;
            }
            if (ctrl.Doors.Any(d => d.Index == index && d != door)) { CycleUiHelper.Alert("错误", $"门编码 {index} 已存在"); return; }

            door.Index = index;
            door.ControlAddress = cAddr;
            door.OpenStatusAddress = oAddr;
            door.NoControl = _doorNoControl;
            SaveData();
            _status = "门已保存";
            CycleUiHelper.Alert("提示", "保存成功");
            _panel?.Repaint();
        }

        private static void ConfirmDeleteDoor()
        {
            var ctrl = GetSelectedController();
            var door = GetSelectedDoor();
            if (ctrl == null || door == null) { CycleUiHelper.Alert("提示", "请选择要删除的门"); return; }
            CycleUiHelper.ConfirmThen($"删除编码为 {door.Index} 的门？", () =>
            {
                ctrl.Doors.Remove(door);
                _selectedDoorIdx = -1;
                ClearDoorFields();
                SaveData();
                _status = "已删除门";
                _panel?.Repaint();
            });
        }

        private static bool TryParseControllerInput(out int index, out string ip, out int port, out string type, bool requireSelection, out string err)
        {
            index = 0; ip = ""; port = 502; type = ""; err = "";
            ip = string.IsNullOrWhiteSpace(_ctrlIp) ? "192.168.1.100" : _ctrlIp.Trim();
            if (!IsValidIp(ip)) { err = "无效的 IP 地址"; return false; }
            if (!int.TryParse(_ctrlPort.Trim(), out port)) { err = "端口必须是数字"; return false; }
            if (!int.TryParse(_ctrlIndex.Trim(), out index))
            {
                index = _controllers.Count > 0 ? _controllers.Max(c => c.Index) + 1 : 1;
                if (!string.IsNullOrWhiteSpace(_ctrlIndex.Trim())) { err = "编码必须是数字"; return false; }
            }
            type = _typeNames.Length > 0 ? _typeNames[_typeIdx] : "ModbusDoorController";
            if (requireSelection && GetSelectedController() == null) { err = "请先选择门控制器"; return false; }
            return true;
        }

        private static bool TryParseDoorInput(out int index, out ushort cAddr, out ushort oAddr, bool requireSelection, out string err)
        {
            index = 0; cAddr = 0; oAddr = 0; err = "";
            var ctrl = GetSelectedController();
            if (requireSelection && (ctrl == null || GetSelectedDoor() == null)) { err = "请先选择门"; return false; }
            if (!int.TryParse(_doorIndex.Trim(), out index))
            {
                index = ctrl?.Doors.Count > 0 ? ctrl.Doors.Max(d => d.Index) + 1 : 1;
                if (!string.IsNullOrWhiteSpace(_doorIndex.Trim())) { err = "门编码必须是数字"; return false; }
            }
            if (!ushort.TryParse(string.IsNullOrWhiteSpace(_doorCtrlAddr) ? "0" : _doorCtrlAddr.Trim(), out cAddr))
            { err = "控制地址必须是 0-65535"; return false; }
            if (!ushort.TryParse(string.IsNullOrWhiteSpace(_doorOpenAddr) ? "0" : _doorOpenAddr.Trim(), out oAddr))
            { err = "开到位地址必须是 0-65535"; return false; }
            return true;
        }

        private static bool IsValidIp(string ip)
        {
            if (string.IsNullOrWhiteSpace(ip)) return false;
            var pattern = @"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
            return Regex.IsMatch(ip, pattern) && IPAddress.TryParse(ip, out var addr)
                && addr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork;
        }
    }
}
