using Quasar.Common.Messages;
using Quasar.Common.Networking;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;

namespace Quasar.Server.Networking
{
    /// <summary>
    /// Mock client for testing purposes. Does not have actual network connection.
    /// </summary>
    public class MockClient : ISender
    {
        public event Client.ClientStateEventHandler ClientState;
        public event Client.ClientReadEventHandler ClientRead;
        public event Client.ClientWriteEventHandler ClientWrite;

        public DateTime ConnectedTime { get; }
        public bool Connected { get; private set; }
        public bool Identified { get; set; }
        public UserState Value { get; set; }
        public IPEndPoint EndPoint { get; }
        public bool IsMock => true;

        private static Random _random = new Random();
        private static string _lastCountryCode = "US";
        private static string _lastCountryName = "United States";

        public MockClient()
        {
            ConnectedTime = DateTime.UtcNow;
            Connected = true;
            Identified = true;

            // Generate random mock data
            var mockIp = $"192.168.{_random.Next(1, 255)}.{_random.Next(1, 255)}";
            var mockPort = _random.Next(10000, 65535);
            EndPoint = new IPEndPoint(IPAddress.Parse(mockIp), mockPort);

            // Get country info (this sets both _lastCountryCode and _lastCountryName)
            var countryInfo = GetRandomCountryInfo();
            
            Value = new UserState
            {
                Version = System.Windows.Forms.Application.ProductVersion,
                OperatingSystem = GetRandomOS(),
                AccountType = _random.Next(0, 2) == 0 ? "Admin" : "User",
                ImageIndex = countryInfo.ImageIndex,
                Country = countryInfo.Name,
                CountryCode = countryInfo.Code,
                Id = Guid.NewGuid().ToString(),
                Username = $"TestUser{_random.Next(100, 999)}",
                PcName = $"PC-{_random.Next(1000, 9999)}",
                Tag = $"MockClient{_random.Next(1000, 9999)}",
                EncryptionKey = "MockEncryptionKey123456789012345"
            };
        }

        public void Send<T>(T message) where T : IMessage
        {
            // Mock client doesn't actually send messages
            // Just invoke the write event for statistics tracking
            OnClientWrite(message, 0);
        }

        public void SendBlocking<T>(T message) where T : IMessage
        {
            // Mock client doesn't actually send messages
            OnClientWrite(message, 0);
        }

        public void Disconnect()
        {
            Connected = false;
            OnClientState(false);
        }

        private void OnClientState(bool connected)
        {
            ClientState?.Invoke(null, connected);
        }

        private void OnClientWrite(IMessage message, int messageLength)
        {
            ClientWrite?.Invoke(null, message, messageLength);
        }

        public bool Equals(Client other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return this.EndPoint.Port.Equals(other.EndPoint.Port);
        }

        public override bool Equals(object obj)
        {
            return this.Equals(obj as Client);
        }

        public override int GetHashCode()
        {
            return this.EndPoint.GetHashCode();
        }

        private static string GetRandomOS()
        {
            string[] osList = new[]
            {
                "Windows 11 Pro 64 Bit",
                "Windows 10 Pro 64 Bit",
                "Windows 10 Home 64 Bit",
                "Windows 11 Home 64 Bit",
                "Windows Server 2022 64 Bit",
                "Windows Server 2019 64 Bit"
            };
            return osList[_random.Next(osList.Length)];
        }

        private class CountryInfo
        {
            public string Code { get; set; }
            public string Name { get; set; }
            public int ImageIndex { get; set; }
        }

        private static CountryInfo GetRandomCountryInfo()
        {
            // These indices match the _imageList array in GeoInformationRetriever.cs
            // The array is alphabetically sorted by country code
            var countries = new List<CountryInfo>
            {
                new CountryInfo { Code = "US", Name = "United States", ImageIndex = 229 },
                new CountryInfo { Code = "GB", Name = "United Kingdom", ImageIndex = 78 },
                new CountryInfo { Code = "DE", Name = "Germany", ImageIndex = 55 },
                new CountryInfo { Code = "FR", Name = "France", ImageIndex = 76 },
                new CountryInfo { Code = "CA", Name = "Canada", ImageIndex = 35 },
                new CountryInfo { Code = "AU", Name = "Australia", ImageIndex = 12 },
                new CountryInfo { Code = "JP", Name = "Japan", ImageIndex = 112 },
                new CountryInfo { Code = "CN", Name = "China", ImageIndex = 46 },
                new CountryInfo { Code = "BR", Name = "Brazil", ImageIndex = 28 },
                new CountryInfo { Code = "IN", Name = "India", ImageIndex = 104 },
                new CountryInfo { Code = "RU", Name = "Russia", ImageIndex = 188 },
                new CountryInfo { Code = "MX", Name = "Mexico", ImageIndex = 154 },
                new CountryInfo { Code = "IT", Name = "Italy", ImageIndex = 109 },
                new CountryInfo { Code = "ES", Name = "Spain", ImageIndex = 67 },
                new CountryInfo { Code = "KR", Name = "South Korea", ImageIndex = 120 }
            };
            
            return countries[_random.Next(countries.Count)];
        }
    }
}
