using System.Text.Json;
using System.Text.Json.Serialization;

namespace HRServer.Models
{
    public static class HorseFactory
    {
        public static string HorseDataPath = "horses.json";
        // Thread-safe Dictionary
        private static Dictionary<ulong, Horse> Horses = new();
        public static Horse? GetHorse(ulong id)
        {
            return Horses.TryGetValue(id, out var horse) ? horse : null;
        }
        public static void AddOrUpdateHorse(Horse horse)
        {
            if (horse == null || horse.Id == null)
                throw new ArgumentNullException(nameof(horse), "Horse or its ID cannot be null.");

            Horses[horse.Id.Value] = horse;
        }
        public static IReadOnlyDictionary<ulong, Horse> GetAllHorses()
        {
            return Horses;
        }
        public static void SaveHorsesToFile()
        {
            var json = JsonSerializer.Serialize(Horses);
            File.WriteAllText(HorseDataPath, json);
        }
        public static void LoadHorsesFromFile()
        {
            if (!File.Exists(HorseDataPath))
                return;

            var json = File.ReadAllText(HorseDataPath);
            Horses = JsonSerializer.Deserialize<Dictionary<ulong, Horse>>(json);
        }
    }

    public class Horse
    {
        // Basic Information
        [JsonPropertyName("id")]
        private ulong? _id;
        [JsonPropertyName("age")]
        private int? _age;
        [JsonPropertyName("name")]
        private string _horseName = string.Empty;
        [JsonPropertyName("gender")]
        private string _gender = string.Empty;
        [JsonPropertyName("breed")]
        private string _breed = string.Empty;
        [JsonPropertyName("link")]
        private string _link = string.Empty;
        [JsonPropertyName("lastDrawnDate")]
        private DateTime _lastDrawnDate = DateTime.Now;

        public ulong? Id
        {
            get => _id;
            set
            {
                _id = value;
                LoadState.BasicInfoLoaded = true;
            }
        }

        public int? Age
        {
            get => _age;
            set
            {
                _age = value;
            }
        }

        public string HorseName
        {
            get => _horseName;
            set
            {
                _horseName = value;
            }
        }

        public string Gender
        {
            get => _gender;
            set
            {
                _gender = value;
            }
        }

        public string Breed
        {
            get => _breed;
            set
            {
                _breed = value;
            }
        }

        public string Link
        {
            get => _link;
            set
            {
                _link = value;
            }
        }
        public DateTime LastDrawnDate
        {
            get => _lastDrawnDate;
            set
            {
                _lastDrawnDate = value;
            }
        }
        private HorseSummary _summary = new();
        public HorseSummary Summary
        {
            get => _summary;
            set
            {
                _summary = value;
                LoadState.SummaryLoaded = true;
            }
        }

        private HorseTraining _training = new();
        public HorseTraining Training
        {
            get => _training;
            set
            {
                _training = value;
                LoadState.TrainingLoaded = true;
            }
        }

        private HorseGenetics _genetics = new();
        public HorseGenetics Genetics
        {
            get => _genetics;
            set
            {
                _genetics = value;
                LoadState.GeneticsLoaded = true;
            }
        }

        private HorseAchievements _achievements = new();
        public HorseAchievements Achievements
        {
            get => _achievements;
            set
            {
                _achievements = value;
                LoadState.AchievementsLoaded = true;
            }
        }

        private HorseHealth _health = new();
        public HorseHealth Health
        {
            get => _health;
            set
            {
                _health = value;
                LoadState.HealthLoaded = true;
            }
        }

        public DataLoadState LoadState { get; set; } = new();

        public bool IsAllDataLoaded()
        {
            return LoadState.IsAllDataLoaded();
        }

        public void PrintLoadState()
        {
            Console.WriteLine("Load State of Horse Data:");
            Console.WriteLine($"- Basic Info Loaded: {LoadState.BasicInfoLoaded}");
            Console.WriteLine($"- Summary Loaded: {LoadState.SummaryLoaded}");
            Console.WriteLine($"- Training Loaded: {LoadState.TrainingLoaded}");
            Console.WriteLine($"- Genetics Loaded: {LoadState.GeneticsLoaded}");
            Console.WriteLine($"- Achievements Loaded: {LoadState.AchievementsLoaded}");
            Console.WriteLine($"- Health Loaded: {LoadState.HealthLoaded}");
        }
    }

    public class DataLoadState
    {
        public bool BasicInfoLoaded { get; set; } = false;
        public bool BasicInfoNeedsRefresh { get; set; } = false;
        public bool SummaryLoaded { get; set; } = false;
        public bool SummaryNeedsRefresh { get; set; } = false;
        public bool TrainingLoaded { get; set; } = false;
        public bool TrainingNeedsRefresh { get; set; } = false;
        public bool GeneticsLoaded { get; set; } = false;
        public bool GeneticsNeedsRefresh { get; set; } = false;
        public bool AchievementsLoaded { get; set; } = false;
        public bool AchievementsNeedsRefresh { get; set; } = false;
        public bool HealthLoaded { get; set; } = false;
        public bool HealthNeedsRefresh { get; set; } = false;

        public bool IsAllDataLoaded()
        {
            return BasicInfoLoaded && SummaryLoaded && TrainingLoaded && GeneticsLoaded && AchievementsLoaded && HealthLoaded;
        }
    }

    public class HorseSummary
    {
        [JsonPropertyName("RelatedIds")]
        public List<string> RelatedIds { get; set; } = new();
    }

    public class HorseTraining
    {
        [JsonPropertyName("Training")]
        public string Training { get; set; } = string.Empty;
    }

    public class HorseGenetics
    {
        [JsonPropertyName("GP")]
        public int GP { get; set; }

        [JsonPropertyName("GeneticPotential")]
        public Dictionary<string, float> GeneticPotential { get; set; } = new();

        [JsonPropertyName("Disciplines")]
        public Dictionary<string, float> Disciplines { get; set; } = new() {
            { "Dressage", 0 },
            { "Driving", 0 },
            { "Endurance", 0 },
            { "Eventing", 0 },
            { "Flat Racing", 0 },
            { "Show Jumping", 0 },
            {"Western Reining", 0 }
        };

        [JsonPropertyName("Colors")]
        public Dictionary<string, string> Colors { get; set; } = new() {
            { "Extension", string.Empty },
            { "Agouti", string.Empty },
            { "Grey", string.Empty},
            { "Creampearl", string.Empty },
            { "Dun", string.Empty },
            { "Champagne", string.Empty },
            { "Silver", string.Empty },
            { "Mushroom", string.Empty },
            { "Frame", string.Empty},
            { "Appaloosa", string.Empty },
            { "PATN1", string.Empty },
            { "MITF", string.Empty },
            { "SW2", string.Empty },
            { "KIT", string.Empty },
            { "RAB", string.Empty},
            { "Seal", string.Empty },
            { "Flaxen", string.Empty }
        };
    }

    public class HorseAchievements
    {
        [JsonPropertyName("ShowResults")]
        public List<double> ShowResults { get; set; } = new();
        [JsonPropertyName("Conformation")]
        public Dictionary<string, string> Conformation { get; set; } = new();
        [JsonPropertyName("ShortConformation")]
        public string ShortConformation { get; set; } = string.Empty;
        [JsonPropertyName("MaxShowResult")]
        public double MaxShowResult { get; set; } = 0;
        [JsonPropertyName("MinShowResult")]
        public double MinShowResult { get; set; } = 0;
        [JsonPropertyName("MaxCompetitionResult")]
        public double MaxCompetitionResult { get; set; } = 0;
        [JsonPropertyName("MinCompetitionResult")]
        public double MinCompetitionResult { get; set; } = 0;
    }

    public class HorseHealth
    {
        [JsonPropertyName("Health")]
        public Dictionary<string, string> Health { get; set; } = new();
    }
}
