using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using CycleGUI;
using SimpleCore;
using StandardScene.Utils;

namespace StandardScene.Charge
{
    /// <summary>
    /// 充电桩管理界面（CycleGUI 版，替代原 WinForms 窗体）。
    /// </summary>
    public class ChargeStationManagementForm
    {
        private const string TableId = "charge-station-list";
        private static readonly string[] StatusFilterNames = { "全部状态", "空闲", "充电中", "故障", "离线" };
        private static readonly string[] TypeNames = { "FRLD高款充电桩", "FRLD矮款充电桩", "牧星充电桩" };
        private static readonly string[] MethodNames = { "地充", "尾充", "侧充" };
        private static readonly string[] CarTypeNames = { "FRLD充电", "牧星充电桩充电" };

        private static readonly ChargeStationDataService DataService = ChargeStationDataService.Instance;
        private static readonly Ping Ping = new Ping();

        private static Panel _panel;
        private static Panel _editDialog;
        private static List<ChargeStation> _snapshot = new List<ChargeStation>();
        private static volatile bool _refreshing;
        private static DateTime _lastFlush = DateTime.MinValue;
        private static readonly TimeSpan FlushInterval = TimeSpan.FromSeconds(3);

        private static int _statusFilterIdx;
        private static string _searchText = "";
        private static string _statsText = "";
        private static string _status = "";

        public void Show() => Open();

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

            _statusFilterIdx = 0;
            _searchText = "";
            _lastFlush = DateTime.MinValue;

            var panel = GUI.DeclarePanel()
                .ShowTitle("充电桩管理系统")
                .SetDefaultDocking(Panel.Docking.None)
                .InitSize(1400, 760)
                .InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
            _panel = panel;
            panel.IfTerminalQuit(() => _panel = null);

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

                if (pb.Button("新增", distinct: "cs-add")) OpenEditDialog(null);
                pb.SameLine(8);
                if (pb.Button("刷新", distinct: "cs-refresh"))
                {
                    DataService.Reload();
                    _lastFlush = DateTime.MinValue;
                    _status = "数据已刷新";
                }
                pb.SameLine(8);
                if (pb.Button("策略配置", distinct: "cs-strategy")) ChargeStrategyConfigForm.Open();
                pb.SameLine(8);
                if (pb.Button("通讯监控", distinct: "cs-comm")) CommunicationMonitorForm.Open();
                pb.SameLine(8);
                if (pb.Button("报警配置", distinct: "cs-alarm")) AlarmConfigManagementForm.Open();
                pb.SameLine(8);
                if (pb.Button("导出", distinct: "cs-export")) ExportData(pb);

                pb.Separator();
                if (pb.DropdownBox("状态筛选", StatusFilterNames, ref _statusFilterIdx))
                    _lastFlush = DateTime.MinValue;
                pb.SameLine(12);
                var (search, _) = pb.TextInput("搜索", _searchText, alwaysReturnString: true, hintText: "编号/名称/IP");
                if (search != _searchText) { _searchText = search; _lastFlush = DateTime.MinValue; }

                EnsureSnapshotFresh();
                var items = FilterSnapshot(_snapshot);
                UpdateStats(_snapshot);

                pb.Label(_statsText);
                pb.Label($"显示 {items.Count} / 共 {_snapshot.Count} 个充电桩");

                pb.Table(TableId,
                    new[]
                    {
                        "编号", "名称", "类型", "充电方式", "站点", "通讯", "状态",
                        "车辆", "电量", "电压", "电流", "启用", "操作"
                    },
                    items.Count, (row, i) =>
                    {
                        var s = items[i];
                        ApplyRowColor(row, s);
                        row.Label(s.StationId);
                        row.Label(s.Name);
                        row.Label(GetTypeText(s.Type));
                        row.Label(GetMethodText(s.ChargeMethod));
                        row.Label(s.SiteId?.ToString() ?? "");
                        row.Label(FormatComm(s.CommStatus));
                        row.Label(GetStatusText(s.Status));
                        row.Label(string.IsNullOrWhiteSpace(s.CurrentVehicle) ? "-" : s.CurrentVehicle);
                        row.Label(s.BatteryLevel > 0 ? $"{s.BatteryLevel:F1}%" : "-");
                        row.Label($"{s.RealTimeVoltage:F1}");
                        row.Label($"{s.RealTimeCurrent:F1}");
                        row.Label(s.Enabled ? "是" : "否");
                        var op = row.ButtonGroup(new[] { "编辑", "删除" }, new[] { "编辑充电桩", "删除充电桩" });
                        if (op == 0) OpenEditDialog(s);
                        else if (op == 1) ConfirmDelete(s);
                    }, height: 16, enableSearch: true);

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

                pb.Panel.Repaint(repaintTimeMs: 1000);
            });
        }

        private static void EnsureSnapshotFresh()
        {
            if (_refreshing) return;
            if (DateTime.Now - _lastFlush < FlushInterval) return;
            _lastFlush = DateTime.Now;
            _refreshing = true;
            Task.Run(() =>
            {
                try
                {
                    var list = DataService.GetAllStations().ToList();
                    foreach (var s in list)
                    {
                        try
                        {
                            s.CommStatus = Ping.Send(s.IpAddress, 1000).Status == IPStatus.Success
                                ? CommunicationStatus.Normal : CommunicationStatus.Error;
                        }
                        catch { s.CommStatus = CommunicationStatus.Error; }
                    }
                    _snapshot = list;
                }
                catch (Exception ex) { _status = $"加载失败: {ex.Message}"; }
                finally { _refreshing = false; _panel?.Repaint(); }
            });
        }

        private static List<ChargeStation> FilterSnapshot(List<ChargeStation> src)
        {
            IEnumerable<ChargeStation> q = src;
            if (_statusFilterIdx > 0)
            {
                var st = GetStatusFromFilterIndex(_statusFilterIdx);
                q = q.Where(s => s.Status == st);
            }
            var text = (_searchText ?? "").Trim().ToLower();
            if (!string.IsNullOrEmpty(text))
            {
                q = q.Where(s => s.StationId.ToLower().Contains(text)
                    || s.Name.ToLower().Contains(text)
                    || (s.IpAddress ?? "").Contains(text)
                    || GetTypeText(s.Type).Contains(text));
            }
            return q.ToList();
        }

        private static void UpdateStats(List<ChargeStation> all)
        {
            _statsText = $"总数: {all.Count} | 空闲: {all.Count(s => s.Status == ChargeStationStatus.Idle)} | " +
                         $"充电中: {all.Count(s => s.Status == ChargeStationStatus.Charging)} | " +
                         $"故障: {all.Count(s => s.Status == ChargeStationStatus.Fault)} | " +
                         $"AGV电池已接入: {all.Count(s => s.Status == ChargeStationStatus.Battery)}";
        }

        private static void OpenEditDialog(ChargeStation existing)
        {
            if (_editDialog != null)
            {
                try { _editDialog.BringToFront(); return; }
                catch { _editDialog = null; }
            }

            bool isAdd = existing == null;
            string stationId = isAdd ? "" : existing.StationId;
            string name = isAdd ? "" : existing.Name;
            int typeIdx = isAdd ? 1 : (int)existing.Type;
            int methodIdx = isAdd ? 0 : (int)existing.ChargeMethod;
            int carTypeIdx = isAdd ? 0 : (int)existing.GroupCarType;
            string ip = isAdd ? "192.168." : existing.IpAddress;
            string port = isAdd ? "2000" : existing.Port.ToString();
            string voltage = isAdd ? "48" : existing.SetVoltage.ToString("F1");
            string current = isAdd ? "32" : existing.SetElectricCurrent.ToString("F1");
            string siteId = isAdd ? "0" : (existing.SiteId?.ToString() ?? "0");
            string remarks = isAdd ? "" : (existing.Remarks ?? "");
            bool enabled = isAdd || existing.Enabled;
            bool shield = !isAdd && existing.ShieldSiteMechanismStatus;
            string err = "";

            var dlg = GUI.DeclarePanel()
                .ShowTitle(isAdd ? "新增充电桩" : $"编辑充电桩 [{existing.StationId}]")
                .SetDefaultDocking(Panel.Docking.None)
                .InitSize(480, 520)
                .InitPos(false, 0, 0, 0.5f, 0.5f, 0.5f, 0.5f);
            _editDialog = dlg;
            dlg.IfTerminalQuit(() => _editDialog = null);

            dlg.Define(pb =>
            {
                if (pb.Closing()) { dlg.Exit(); _editDialog = null; return; }

                var (sid, _) = pb.TextInput("1. 编号 (1-99)", stationId, alwaysReturnString: true);
                stationId = sid;
                var (nm, _) = pb.TextInput("2. 名称", name, alwaysReturnString: true);
                name = nm;
                pb.DropdownBox("3. 类型", TypeNames, ref typeIdx);
                pb.DropdownBox("4. 充电方式", MethodNames, ref methodIdx);
                pb.DropdownBox("5. 停靠车型", CarTypeNames, ref carTypeIdx);
                var (ipT, _) = pb.TextInput("6. IP", ip, alwaysReturnString: true);
                ip = ipT;
                var (pt, _) = pb.TextInput("7. 端口", port, alwaysReturnString: true);
                port = pt;
                var (vt, _) = pb.TextInput("8. 电压", voltage, alwaysReturnString: true);
                voltage = vt;
                var (ct, _) = pb.TextInput("9. 电流", current, alwaysReturnString: true);
                current = ct;
                var (site, _) = pb.TextInput("10. 站点ID", siteId, alwaysReturnString: true);
                siteId = site;
                var (rm, _) = pb.TextInput("11. 备注", remarks, alwaysReturnString: true);
                remarks = rm;
                pb.CheckBox("12. 启用", ref enabled);
                if (methodIdx == (int)ChargeMethodType.Side)
                    pb.CheckBox("13. 屏蔽机构状态交互", ref shield);

                if (!isAdd)
                {
                    pb.SeparatorText("实时状态（只读）");
                    pb.Label($"车辆: {(string.IsNullOrWhiteSpace(existing.CurrentVehicle) ? "-" : existing.CurrentVehicle)}");
                    pb.Label($"电量: {(existing.BatteryLevel > 0 ? $"{existing.BatteryLevel:F1}%" : "-")}");
                    pb.Label($"通讯: {FormatComm(existing.CommStatus)} | 机构: {FormatMech(existing.MechanismStatus)}");
                    pb.Label($"报警: {FormatAlarm(existing)}");
                }

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

                pb.Separator();
                if (pb.Button("保存", distinct: "cs-edit-save"))
                {
                    if (!TryBuildStation(isAdd, existing, stationId, name, typeIdx, methodIdx, carTypeIdx,
                            ip, port, voltage, current, siteId, remarks, enabled, shield, out var station, out err))
                        return;

                    string errorMessage;
                    bool ok = isAdd
                        ? DataService.AddStation(station, out errorMessage)
                        : DataService.UpdateStation(station, out errorMessage, true);

                    if (!ok) { err = errorMessage; return; }

                    var mapSite = SimpleLib.GetSite(station.SiteId ?? 0);
                    if (mapSite != null)
                    {
                        mapSite.name = station.Name;
                        mapSite.fields["setVoltage"] = station.SetVoltage.ToString();
                        mapSite.fields["setElectricCurrent"] = station.SetElectricCurrent.ToString();
                        mapSite.fields["group"] = station.Enabled ? station.GroupCarType.ToString() : "禁用";
                    }

                    _lastFlush = DateTime.MinValue;
                    _status = "保存成功";
                    CycleUiHelper.Alert("提示", "保存成功");
                    dlg.Exit();
                    _editDialog = null;
                    _panel?.Repaint();
                }
                pb.SameLine(8);
                if (pb.Button("取消", distinct: "cs-edit-cancel")) { dlg.Exit(); _editDialog = null; }
            });
        }

        private static bool TryBuildStation(bool isAdd, ChargeStation existing, string stationId, string name,
            int typeIdx, int methodIdx, int carTypeIdx, string ip, string port, string voltage, string current,
            string siteIdText, string remarks, bool enabled, bool shield,
            out ChargeStation station, out string err)
        {
            station = new ChargeStation();
            err = "";
            stationId = (stationId ?? "").Trim();
            if (string.IsNullOrEmpty(stationId) || !int.TryParse(stationId, out var num) || num < 1 || num > 99)
            { err = "充电桩编号必须是 1-99 之间的数字"; return false; }

            if (isAdd && DataService.GetAllStations().Any(s => s.StationId == stationId))
            { err = $"充电桩编号 {stationId} 已存在"; return false; }

            if (!int.TryParse((siteIdText ?? "").Trim(), out var siteId))
            { err = "站点ID必须是数字"; return false; }
            var site = SimpleLib.GetSite(siteId);
            if (site == null) { err = $"站点ID {siteId} 未在调度系统上"; return false; }

            if (!int.TryParse((port ?? "").Trim(), out var portNum)) { err = "端口必须是数字"; return false; }
            if (!double.TryParse((voltage ?? "").Trim(), out var volt)) { err = "电压格式无效"; return false; }
            if (!double.TryParse((current ?? "").Trim(), out var amp)) { err = "电流格式无效"; return false; }

            station.StationId = stationId;
            station.Name = (name ?? "").Trim();
            station.Type = (ChargeStationType)typeIdx;
            station.ChargeMethod = (ChargeMethodType)methodIdx;
            station.GroupCarType = (ChargeStationCarType)carTypeIdx;
            station.IpAddress = (ip ?? "").Trim();
            station.Port = portNum;
            station.SetVoltage = volt;
            station.SetElectricCurrent = amp;
            station.Enabled = enabled;
            station.ShieldSiteMechanismStatus = shield;
            station.SiteId = siteId > 0 ? siteId : (int?)null;
            station.Remarks = remarks ?? "";
            return true;
        }

        private static void ConfirmDelete(ChargeStation station)
        {
            CycleUiHelper.ConfirmThen($"确定删除充电桩 [{station.StationId}] {station.Name}？", () =>
            {
                if (!DataService.DeleteStation(station.StationId, out var err))
                {
                    CycleUiHelper.Alert("错误", $"删除失败: {err}");
                    return;
                }
                var site = SimpleLib.GetSite(station.SiteId ?? 0);
                if (site != null)
                {
                    site.name = "NoName";
                    site.fields.Remove("setVoltage");
                    site.fields.Remove("setElectricCurrent");
                    site.fields.Remove("Charge");
                    site.fields.Remove("group");
                }
                _lastFlush = DateTime.MinValue;
                _status = "删除成功";
                _panel?.Repaint();
            });
        }

        private static void ExportData(PanelBuilder pb)
        {
            if (!pb.SaveFile("导出充电桩", "*.json;*.csv", out var path) || string.IsNullOrEmpty(path)) return;
            try
            {
                var stations = DataService.GetAllStations();
                if (path.EndsWith(".csv", StringComparison.OrdinalIgnoreCase))
                {
                    var csv = new StringBuilder("编号,名称,类型,IP,端口,电压,电流,状态,启用,车型,站点ID,备注\n");
                    foreach (var s in stations)
                    {
                        csv.Append($"{s.StationId},{s.Name},{GetTypeText(s.Type)},{s.IpAddress},{s.Port}," +
                                     $"{s.SetVoltage},{s.SetElectricCurrent},{GetStatusText(s.Status)}," +
                                     $"{(s.Enabled ? "是" : "否")},{s.GroupCarType},{s.SiteId},{s.Remarks}\n");
                    }
                    File.WriteAllText(path, csv.ToString(), Encoding.UTF8);
                }
                else
                {
                    File.WriteAllText(path, Newtonsoft.Json.JsonConvert.SerializeObject(stations, Newtonsoft.Json.Formatting.Indented));
                }
                CycleUiHelper.Alert("提示", "导出成功");
            }
            catch (Exception ex) { CycleUiHelper.Alert("错误", $"导出失败: {ex.Message}"); }
        }

        private static void ApplyRowColor(PanelBuilder.Row row, ChargeStation s)
        {
            if (s.HasAlarm) row.SetColor(Color.FromArgb(255, 205, 210));
            else if (s.Status == ChargeStationStatus.Idle) row.SetColor(Color.FromArgb(232, 245, 233));
            else if (s.Status == ChargeStationStatus.Charging) row.SetColor(Color.FromArgb(200, 230, 201));
            else if (s.Status == ChargeStationStatus.Fault) row.SetColor(Color.FromArgb(255, 205, 210));
            else if (s.Status == ChargeStationStatus.Battery) row.SetColor(Color.FromArgb(238, 238, 238));
        }

        private static ChargeStationStatus GetStatusFromFilterIndex(int idx) => idx switch
        {
            1 => ChargeStationStatus.Idle,
            2 => ChargeStationStatus.Charging,
            3 => ChargeStationStatus.Fault,
            4 => ChargeStationStatus.Battery,
            _ => ChargeStationStatus.Idle
        };

        private static string GetStatusText(ChargeStationStatus status) => status switch
        {
            ChargeStationStatus.Idle => "空闲",
            ChargeStationStatus.Charging => "充电中",
            ChargeStationStatus.Fault => "故障",
            ChargeStationStatus.Battery => "AGV电池已接入",
            _ => "未知"
        };

        private static string GetTypeText(ChargeStationType type) => type switch
        {
            ChargeStationType.FRLDTall => "FRLD高款充电桩",
            ChargeStationType.FRLDShort => "FRLD矮款充电桩",
            ChargeStationType.MuXing => "牧星充电桩",
            _ => "未知"
        };

        private static string GetMethodText(ChargeMethodType m) => m switch
        {
            ChargeMethodType.Ground => "地充",
            ChargeMethodType.Rear => "尾充",
            ChargeMethodType.Side => "侧充",
            _ => "未知"
        };

        private static string FormatComm(CommunicationStatus s) => s switch
        {
            CommunicationStatus.Normal => "✓ 正常",
            CommunicationStatus.Delayed => "⚠ 延迟",
            CommunicationStatus.Timeout => "✗ 超时",
            CommunicationStatus.Disconnected => "✗ 断开",
            CommunicationStatus.Error => "✗ 错误",
            _ => "? 未知"
        };

        private static string FormatMech(MechanismStatus s) => s switch
        {
            MechanismStatus.Extended => "◆ 伸出",
            MechanismStatus.Retracted => "◇ 缩回",
            MechanismStatus.Extending => "▶ 运动中",
            _ => "? 未知"
        };

        private static string FormatAlarm(ChargeStation s)
        {
            if (!s.HasAlarm) return "正常";
            return string.IsNullOrWhiteSpace(s.AlarmMessage) ? $"【{s.AlarmLevel}】" : s.AlarmMessage;
        }
    }
}
