using System;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Utils;

namespace Network
{
    public class UnityTcpClient : Singleton<UnityTcpClient>
    {
        private TcpClient _tcpClient;
        public bool IsConnected => _tcpClient?.Connected ?? false;

        /// <summary>
        ///     尝试连接到指定的地址和端口
        /// </summary>
        /// <param name="address">服务器地址</param>
        /// <param name="port">端口号</param>
        /// <returns>连接是否成功</returns>
        public async Task<bool> Connect(string address, int port)
        {
            if (IsConnected)
            {
                Debug.LogWarning("Already connected to a server.");
                return true;
            }

            try
            {
                // 创建一个新的 TcpClient 实例
                _tcpClient = new TcpClient();

                // 尝试连接到指定的地址和端口
                await _tcpClient.ConnectAsync(address, port);

                // 如果连接成功
                if (IsConnected)
                {
                    Debug.Log($"Successfully connected to server at {address}:{port}");
                    return true;
                }
            }
            catch (SocketException ex)
            {
                Debug.LogError($"Failed to connect to server at {address}:{port}. Error: {ex.Message}");
            }
            catch (Exception ex)
            {
                Debug.LogError($"An unexpected error occurred: {ex.Message}");
            }

            // 如果发生任何错误或连接失败
            Disconnect();
            return false;
        }

        /// <summary>
        ///     断开与服务器的连接
        /// </summary>
        public void Disconnect()
        {
            if (!IsConnected)
            {
                Debug.LogWarning("Not currently connected to any server.");
                return;
            }

            try
            {
                // 关闭 TcpClient 连接
                _tcpClient?.Close();

                Debug.Log("Disconnected from the server.");
            }
            catch (Exception ex)
            {
                Debug.LogError($"Error while disconnecting: {ex.Message}");
            }
        }

        /// <summary>
        ///     发送数据到服务器
        /// </summary>
        /// <param name="message">要发送的消息</param>
        public async Task Send(string message)
        {
            if (!IsConnected)
            {
                Debug.LogError("Cannot send data. Not connected to any server.");
                return;
            }

            try
            {
                // 获取网络流
                var stream = _tcpClient.GetStream();

                // 将消息转换为字节数组
                var data = Encoding.UTF8.GetBytes(message);

                // 发送数据
                await stream.WriteAsync(data, 0, data.Length);

                Debug.Log($"Sent message to server: {message}");
            }
            catch (Exception ex)
            {
                Debug.LogError($"Error while sending: {ex.Message}");
            }
        }

        /// <summary>
        ///     接收来自服务器的数据
        /// </summary>
        /// <returns>接收到的消息</returns>
        public async Task<string> Receive()
        {
            if (!IsConnected)
            {
                Debug.LogError("Cannot receive data. Not connected to any server.");
                return null;
            }

            try
            {
                // 获取网络流
                var stream = _tcpClient.GetStream();

                // 检查是否有可用数据
                if (stream.DataAvailable)
                {
                    // 读取数据
                    var buffer = new byte[1024];
                    var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);

                    // 将字节数组转换为字符串
                    var message = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                    Debug.Log($"Received message from server: {message}");
                    return message;
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"Error while receiving: {ex.Message}");
            }

            return null;
        }
    }
}