using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Newtonsoft.Json;

namespace NoticeServer
{
    /// <summary>
    /// 연결된 채팅 클라이언트 정보 및 통신 관리
    /// </summary>
    public class ChatClient
    {
        private TcpClient tcpClient;
        private NetworkStream stream;
        private Thread receiveThread;
        private bool isConnected;

        /// <summary>클라이언트 고유 ID</summary>
        public string ClientId { get; private set; }

        /// <summary>닉네임</summary>
        public string NickName { get; set; }

        /// <summary>사원번호 (Employee ID)</summary>
        public string EmployeeId { get; set; }

        /// <summary>사용자 그룹</summary>
        public string UserGroup { get; set; }

        /// <summary>IP 주소</summary>
        public string IpAddress { get; private set; }

        /// <summary>호스트명</summary>
        public string HostName { get; set; }

        /// <summary>연결 시간</summary>
        public DateTime ConnectedTime { get; private set; }

        /// <summary>마지막 활동 시간</summary>
        public DateTime LastActivity { get; set; }

        /// <summary>메시지 수신 이벤트</summary>
        public event EventHandler<ChatMessage> MessageReceived;

        /// <summary>연결 해제 이벤트</summary>
        public event EventHandler<string> Disconnected;

        public ChatClient(TcpClient client)
        {
            tcpClient = client;
            stream = client.GetStream();
            isConnected = true;
            ClientId = Guid.NewGuid().ToString();
            ConnectedTime = DateTime.Now;
            LastActivity = DateTime.Now;

            var endpoint = client.Client.RemoteEndPoint.ToString();
            IpAddress = endpoint.Split(':')[0];

            StartReceiving();
        }

        /// <summary>
        /// 메시지 수신 스레드 시작
        /// </summary>
        private void StartReceiving()
        {
            receiveThread = new Thread(ReceiveLoop)
            {
                IsBackground = true,
                Name = $"ChatClient-{ClientId}"
            };
            receiveThread.Start();
        }

        /// <summary>
        /// 메시지 수신 루프
        /// </summary>
        private void ReceiveLoop()
        {
            byte[] buffer = new byte[4096];

            try
            {
                while (isConnected && tcpClient.Connected)
                {
                    int bytesRead = stream.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                    {
                        // Connection closed
                        break;
                    }

                    string jsonData = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    var message = JsonConvert.DeserializeObject<ChatMessage>(jsonData);

                    if (message != null)
                    {
                        LastActivity = DateTime.Now;

                        // Set nickname, employeeId, userGroup from Connect message
                        if (message.Type == MessageType.Connect && !string.IsNullOrEmpty(message.NickName))
                        {
                            NickName = message.NickName;
                            EmployeeId = message.EmployeeId;
                            UserGroup = message.UserGroup;
                            HostName = message.HostName;
                        }

                        MessageReceived?.Invoke(this, message);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Client {NickName ?? ClientId} receive error: {ex.Message}");
            }
            finally
            {
                Disconnect();
            }
        }

        /// <summary>
        /// Send message
        /// </summary>
        public bool SendMessage(ChatMessage message)
        {
            if (!isConnected || !tcpClient.Connected)
                return false;

            try
            {
                string jsonData = JsonConvert.SerializeObject(message);
                byte[] data = Encoding.UTF8.GetBytes(jsonData);
                stream.Write(data, 0, data.Length);
                stream.Flush();
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] Client {NickName ?? ClientId} send error: {ex.Message}");
                Disconnect();
                return false;
            }
        }

        /// <summary>
        /// 연결 해제
        /// </summary>
        public void Disconnect()
        {
            if (!isConnected)
                return;

            isConnected = false;

            try
            {
                stream?.Close();
                tcpClient?.Close();
            }
            catch { }

            Disconnected?.Invoke(this, ClientId);
        }

        public override string ToString()
        {
            return $"{NickName ?? "Unknown"} ({IpAddress})";
        }
    }
}
