using Simple3.RCS;
using Simple3.RCS.CarTypes;
using SimpleCore;
using SimpleCore.Library;
using SimpleCore.PropType;
using StandardScene.Charge;
using StandardScene.TCP;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;

namespace StandardScene.ChargeStationType

{
    public class MuXingChargeStation : AbstractChargeStation
    {
        public static TcpListener tcpListener;
        public static Thread listenerThread;
        public static NetworkStream stream;
        public static TcpClient client;
        //public Dictionary<IPAddress, (TcpClient, NetworkStream)> chargeClient = new Dictionary<IPAddress, (TcpClient, NetworkStream)> { };
        public System.Timers.Timer _Timer;
        public bool reciveHeartBeat;
        public bool running;
        public byte[] IdBytes = new byte[] { 0x0f, 0x01 };
        private static IPEndPoint _endPoint;

        /// <summary>
        /// 关闭当前TCP连接
        /// </summary>
        public override void CloseCommunication()
        {
            try
            {
                running = false;

                // 停止定时器
                if (_Timer != null)
                {
                    _Timer.Stop();
                    _Timer.Dispose();
                    _Timer = null;
                }

                // 关闭流
                if (stream != null)
                {
                    stream.Close();
                    stream = null;
                }

                // 关闭客户端
                if (client != null)
                {
                    client.Close();
                    client = null;
                }

                // 停止监听器
                if (tcpListener != null)
                {
                    tcpListener.Stop();
                    tcpListener = null;
                }

                Diagnosis.Log($"MuXingChargeStation[{SiteId}] TCP connection closed");
            }
            catch (Exception ex)
            {
                Diagnosis.Log($"ERR:MuXingChargeStation[{SiteId}] failed to close connection: {ex.Message}");
            }
        }

        public override void CreateCommunication(IPAddress ip, int port)
        {
            // 先关闭旧连接
            CloseCommunication();

            _endPoint = new IPEndPoint(ip, port);
            reciveHeartBeat = false;
            running = true;
            int n = 0;
            DateTime offlineTime = DateTime.Now;
            try
            {
                tcpListener = new TcpListener(ip, port);
                tcpListener.Start();
                Diagnosis.Post($"AGV与牧星充电站通信已建立，监听 IP: {ip}, 端口: {port}");
                client = tcpListener.AcceptTcpClient();
                client.SendTimeout = 5000;
                client.ReceiveTimeout = 5000;
                stream = client.GetStream();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"与充电站通信建立失败: {ExceptionFormatter.FormatEx(ex)}");
                throw;
            }

            while (running)
            {
                try
                {
                    if (client == null)
                    {
                        client = tcpListener.AcceptTcpClient();
                        client.SendTimeout = 5000;
                        client.ReceiveTimeout = 5000;
                        stream = client.GetStream();
                    }

                    var type = ReceiveMesageType();
                    //item1:byte0  帧头
                    //item2:byte11 命令字
                    //item3:byte12 动作码/故障码/状态码
                    //item4:byte5  设备ID 低
                    //item5:byte6  设备ID 高

                    //0x10 充电桩登录回复 1次
                    if (type.Item1 == 0xAA && type.Item2 == 0x10)
                    {
                        var timestampBytes = GetTimeStamp();
                        byte[] dataByte = new byte[16]
                        {
                            0, 0x0d,
                            0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0x10,
                            0, 0,
                            0x00, 0x00
                        }; //长度必须大于10,与帧长度对应
                        dataByte = InitSendBytes(dataByte, type, timestampBytes);
                        byte[] mesSendByte =
                            CombineDataAndCRC(dataByte, CalculateCRC16(dataByte.Skip(1).ToArray())); //拼接crc（去掉包头）
                        Diagnosis.Post($"login => {string.Join(" ", mesSendByte.Select(d => $"{d:X2}"))}",
                            $"充电桩登录回复");
                        SendMessage(mesSendByte);
                    }
                    //0x12 充电桩对接完成回复 1次
                    else if (type.Item1 == 0xAA && type.Item2 == 0x12)
                    {
                        var timestampBytes = GetTimeStamp();
                        byte[] dataByte = new byte[12]
                        {
                            0, 0x09,
                            0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0x12
                        };
                        ;
                        dataByte = InitSendBytes(dataByte, type, timestampBytes);
                        byte[] sendByte =
                            CombineDataAndCRC(dataByte, CalculateCRC16(dataByte.Skip(1).ToArray())); //拼接crc（去掉包头）
                        Diagnosis.Post($"docking => {string.Join(" ", sendByte.Select(d => $"{d:X2}"))}",
                            $"充电桩对接完成回复");
                        SendMessage(sendByte);
                    }
                    //0x13 故障上报回复
                    else if (type.Item1 == 0xAA && type.Item2 == 0x13)
                    {
                        var timestampBytes = GetTimeStamp();
                        byte[] dataByte = new byte[13]
                        {
                            0, 0x0A,
                            0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0x13,
                            type.Item3
                        };
                        dataByte = InitSendBytes(dataByte, type, timestampBytes);
                        byte[] sendByte =
                            CombineDataAndCRC(dataByte, CalculateCRC16(dataByte.Skip(1).ToArray())); //拼接crc（去掉包头）
                        Diagnosis.Post($"Error => {string.Join(" ", sendByte.Select(d => $"{d:X2}"))}",
                            $"故障上报回复");
                        SendMessage(sendByte);
                    }

                    //收到至少1次充电桩心跳包上传 
                    if (type.Item1 == 0xAA && type.Item2 == 0xF0 && !reciveHeartBeat)
                    {
                        Diagnosis.Post($"收到充电桩心跳包上传", $"HeartBeatRecive");
                        reciveHeartBeat = true;
                        StartSendingHeartBeat();
                    }

                    //异常情况处理
                    //故障上报 故障码不为0 16 17 1
                    if (type.Item1 == 0xAA && type.Item2 == 0x13 &&
                        (type.Item3 != 0 && type.Item3 != 16 && type.Item3 != 17 && type.Item3 != 1))
                    {
                        //充电桩掉线
                        if ((type.Item3 & (1 << 3)) != 0 && reciveHeartBeat)
                        {
                            if (n == 0) offlineTime = DateTime.Now;
                            //充电桩掉线时间大于60s  重启WiFi模块
                            if ((DateTime.Now - offlineTime).TotalSeconds > 60)
                            {
                                var timestampBytes = GetTimeStamp();
                                //下发 命令码指令
                                byte[] dataByte = new byte[17]
                                {
                                        0, 0x0E,
                                        0, 0, 0, 0, 0, 0, 0, 0, 0,
                                        0x15,
                                        0x04, //重启WiFi模块
                                        0x00, 0x00, 0x00, 0x00
                                };
                                dataByte = InitSendBytes(dataByte, type, timestampBytes);
                                byte[] sendChargeByte =
                                    CombineDataAndCRC(dataByte, CalculateCRC16(dataByte.Skip(1).ToArray()));
                                Diagnosis.Post(
                                    $"Restart => {string.Join(" ", sendChargeByte.Select(d => $"{d:X2}"))}",
                                    $"重启WiFi模块");
                                SendMessage(sendChargeByte);
                                n = 0;
                                offlineTime = DateTime.Now;
                            }

                            n++;
                        }
                        else
                        {
                            n = 0;
                            offlineTime = DateTime.Now;
                        }
                    }

                    //if (!client.Connected)
                    //{
                    //    Console.WriteLine("客户端断开连接，退出循环");
                    //    running = false;
                    //}

                }
                catch (Exception ex)
                {
                    Console.WriteLine($"充电桩通信异常：{ExceptionFormatter.FormatEx(ex)}");
                    running = false;
                    client.Close();
                    tcpListener.Stop();
                    stream.Close();
                }

            }
        }

        public override void SendToChargeStation(int isCharge, Car car,Site site)
        {
            var messageService = CommunicationMessageService.Instance;
            float setVoltage = 55.0f;
            float setElectricCurrent = 50.0f;
            float voltage = 430;
           // Site site = null;
            if (car != null)
            {
               // site = SimpleLib.GetSite(car.status.holdingLocks.FirstOrDefault());
                
              
                int carId = 0;
                if (car != null && car.GetType() != typeof(DummyCar))
                {
                    voltage = float.Parse(Commons.GetCarStatus(car, "Voltage")) * 10;
                    voltage = voltage > 430 ? voltage : 430;
                    carId = car.id;
                }
            }
            if (site != null && site.fields.ContainsKey("setVoltage") && site.fields.ContainsKey("setElectricCurrent"))
            {
                setVoltage = float.Parse(site.fields["setVoltage"]);
                setElectricCurrent = float.Parse(site.fields["setElectricCurrent"]);
            }

            var byte1 = BitConverter.GetBytes(voltage);
            var type = ReceiveMesageType();
            var openChargePort = isCharge == 1 ? 2 : 3;
            //下发打开充电口指令
            var timestampBytes = GetTimeStamp();
            byte[] dataByte = new byte[18]
            {
                    0, 0x0F,
                    0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0x11,
                    (byte)openChargePort,//开始充电/结束充电
                    byte1[0], byte1[1],
                    0xc8, 0x00,//下发最大充电电流
                    0x02//电池种类
            };
            dataByte = InitSendBytes(dataByte, type, timestampBytes);
            byte[] openCharge =
                CombineDataAndCRC(dataByte, CalculateCRC16(dataByte.Skip(1).ToArray()));
            if (client.Connected)
            {
                stream.WriteAsync(openCharge, 0, openCharge.Length);
                stream.FlushAsync();
            }
            messageService.AddSendMessage(_endPoint.Address.ToString(), _endPoint.Port, BitConverter.ToString(openCharge).Replace("-", " "), site?.name, "MuXing");
            Diagnosis.Post($"openCharge => {string.Join(" ", openCharge.Select(d => $"{d:X2}"))}",
                $"下发开始充电");

        }

        public void StartSendingHeartBeat()
        {
            if (client == null)
            {
                Console.WriteLine("客户端为null，无法启动心跳包定时器");
                return;
            }
            _Timer = new System.Timers.Timer(2000);
            _Timer.Elapsed += SendHeartBeat;
            _Timer.AutoReset = true; // 反复执行
            _Timer.Enabled = true;

        }

        private void SendHeartBeat(Object item, ElapsedEventArgs e)
        {
            var timestampBytes = GetTimeStamp();
            var type = ReceiveMesageType();
            //下发心跳包报文
            var rcs = new byte[]
            {
                0xBB, 0x09, 0x00, 0x03, 0x00,
                IdBytes[0], IdBytes[1],
                timestampBytes[0], timestampBytes[1], timestampBytes[2], timestampBytes[3],
                0xF0
            };
            byte[] mesSendByte = CombineDataAndCRC(rcs, CalculateCRC16(rcs.Skip(1).ToArray()));
            // 日志记录
            Diagnosis.Post($"heartBeat => {string.Join(" ", mesSendByte.Select(d => $"{d:X2}"))}", $"下发心跳包");
            // 发送心跳包
            SendMessage(mesSendByte);
        }

        private byte[] GetTimeStamp()
        {
            // 获取当前时间戳（秒级别）
            int timestamp = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            //将时间戳转换为字节数组，低字节在前
            byte[] timestampBytes = BitConverter.GetBytes(timestamp);
            return timestampBytes;
        }

        private static Tuple<byte, byte, byte, byte, byte> ReceiveMesageType()
        {
            byte[] message = new byte[1024];
            int bytesRead = 0;
            try
            {
                if (client != null && client.Connected && stream != null && stream.CanRead && client.Available > 0)
                {
                    bytesRead = stream.Read(message, 0, 1024);
                }
            }
            catch (Exception ex)
            {
                client = null;
                stream = null;
                Console.WriteLine($"Error reading message: {ex.Message}");
            }

            //message长度判断：至少需要 13 字节才能安全访问 message[12]
            if (bytesRead >= 13)
            {

                string receivedMessage = BitConverter.ToString(message, 0, bytesRead);
                Diagnosis.Post($"Received <= {string.Join(" ", message.Take(bytesRead).ToArray().Select(d => $"{d:X2}"))}", "读取报文");
                Diagnosis.Post($"item1:{message[0]:x2},item2:{message[11]:x2},item3:{message[12]:x2},item4:{message[5]:x2},item5:{message[6]:x2},", "Tuple.Item");
                var messageService = CommunicationMessageService.Instance;
                messageService.AddReceiveMessage(_endPoint.Address.ToString(), _endPoint.Port, string.Join(",", message), "MuXing");
                return Tuple.Create<byte, byte, byte, byte, byte>(message[0], message[11], message[12], message[5], message[6]);
            }
            return new Tuple<byte, byte, byte, byte, byte>(0, 0, 0, 0, 0);
        }

        public static byte[] CombineDataAndCRC(byte[] data, byte[] crc)
        {
            //byte[] crcBytes = BitConverter.GetBytes(crc);
            // 合并数据和CRC
            byte[] combined = new byte[data.Length + crc.Length];
            Array.Copy(data, combined, data.Length);
            Array.Copy(crc, 0, combined, data.Length, crc.Length);

            return combined;
        }

        private static byte[] CalculateCRC16(byte[] data)
        {
            byte b = byte.MaxValue;
            byte b2 = byte.MaxValue;
            byte b3 = 1;
            byte b4 = 160;
            for (int i = 0; i < data.Length; i++)
            {
                b = (byte)(b ^ data[i]);
                for (int j = 0; j <= 7; j++)
                {
                    byte b5 = b2;
                    byte b6 = b;
                    b2 = (byte)(b2 >> 1);
                    b = (byte)(b >> 1);
                    if ((b5 & 1) == 1)
                    {
                        b = (byte)(b | 0x80u);
                    }
                    if ((b6 & 1) == 1)
                    {
                        b2 = (byte)(b2 ^ b4);
                        b = (byte)(b ^ b3);
                    }
                }
            }
            return new byte[2]
            {
                b,b2
            };
        }

        private void SendMessage(byte[] message)
        {
            try
            {
                if (client != null && stream != null)
                {
                    stream.Write(message, 0, message.Length);
                    stream.Flush();
                }
            }
            catch (Exception ex)
            {
                client = null;
                Console.WriteLine($"Error sending message: {ExceptionFormatter.FormatEx(ex)}");
            }
        }

        private byte[] InitSendBytes(byte[] sendBytes, Tuple<byte, byte, byte, byte, byte> type, byte[] timestampBytes)
        {
            sendBytes[0] = 0xBB;        //帧头
            sendBytes[2] = 0x00;        //帧长 高
            sendBytes[3] = 0x03;        //设备类型 低
            sendBytes[4] = 0x00;        //设备类型 高
            sendBytes[5] = IdBytes[0];  //设备ID 低
            sendBytes[6] = IdBytes[1];  //设备ID 高
            sendBytes[7] = timestampBytes[0];   //时间戳 低
            sendBytes[8] = timestampBytes[1];
            sendBytes[9] = timestampBytes[2];
            sendBytes[10] = timestampBytes[3];  //时间戳 高
            return sendBytes;
        }
    }
}
