using System.Text.RegularExpressions;
using PetCompanion.Models;
using PetCompanion.Models.Enums;

namespace PetCompanion.Repositories
{
    public class ItemRepository
    {
        private readonly Dictionary<string, Item> _itemTemplates = new();
        private readonly Dictionary<ItemRarity, List<string>> _itemsByRarity = new();
        private readonly Random _random = new();

        public ItemRepository()
        {
            foreach (ItemRarity rarity in Enum.GetValues(typeof(ItemRarity)))
            {
                _itemsByRarity[rarity] = new List<string>();
            }
            LoadItemsFromCsv();
        }

        private void LoadItemsFromCsv()
        {
            var lines = File.ReadAllLines("Items.csv").Skip(1); // Skip header
            foreach (var line in lines)
            {
                var parts = line.Split(',');
                var name = parts[0];
                var type = Enum.Parse<ItemType>(parts[1]);
                var rarity = Enum.Parse<ItemRarity>(parts[2]);
                var description = parts[3];

                Item item = type switch
                {
                    ItemType.Consumable => CreateConsumableItem(name, description, rarity),
                    ItemType.Equipment => CreateEquipmentItem(name, description, rarity),
                    ItemType.Material => CreateMaterialItem(name, description, rarity),
                    _ => throw new ArgumentException($"Unknown item type: {type}")
                };

                _itemTemplates.Add(name, item);
                _itemsByRarity[rarity].Add(name);
            }
        }

        private Item CreateConsumableItem(string name, string description, ItemRarity rarity)
        {
            var item = new ConsumableItem
            {
                Id = Guid.NewGuid().ToString(),
                Name = name,
                Description = description,
                Type = ItemType.Consumable,
                Rarity = rarity
            };

            // Parse effects from description
            if (description.Contains("food resources"))
            {
                var foodAmount = int.Parse(Regex.Match(description, @"\+(\d+) food").Groups[1].Value);
                item.Effect = (pet) => pet.Resources.Food += foodAmount;
            }
            else if (description.Contains("Intelligence"))
            {
                var amount = int.Parse(Regex.Match(description, @"\+(\d+)").Groups[1].Value);
                item.Effect = (pet) => pet.IncrementIntelligence(amount);
            }
            // Add more effect parsing as needed

            return item;
        }

        private Item CreateEquipmentItem(string name, string description, ItemRarity rarity)
        {
            var equipment = new StatBoostEquipment
            {
                Id = Guid.NewGuid().ToString(),
                Name = name,
                Description = description,
                Type = ItemType.Equipment,
                Rarity = rarity
            };

            // Parse slot and stats from description
            var slotMatch = Regex.Match(description, @"(Helmet|Chest|Legging|Weapon):");
            if (slotMatch.Success)
            {
                equipment.Slot = Enum.Parse<EquipmentSlot>(slotMatch.Groups[1].Value);
            }

            var statMatch = Regex.Match(description, @"\+(\d+) Max (\w+)");
            if (statMatch.Success)
            {
                var amount = int.Parse(statMatch.Groups[1].Value);
                var stat = statMatch.Groups[2].Value;
                equipment.StatBoosts.Add(stat, amount);
            }

            return equipment;
        }

        private Item CreateMaterialItem(string name, string description, ItemRarity rarity)
        {
            return new MaterialItem
            {
                Id = Guid.NewGuid().ToString(),
                Name = name,
                Description = description,
                Type = ItemType.Material,
                Rarity = rarity
            };
        }

        public Item CreateItem(string itemName)
        {
            if (_itemTemplates.TryGetValue(itemName, out var template))
            {
                // Create a new instance with a new ID but same properties
                var json = System.Text.Json.JsonSerializer.Serialize(template);
                var newItem = System.Text.Json.JsonSerializer.Deserialize<Item>(json);
                newItem.Id = Guid.NewGuid().ToString();
                return newItem;
            }

            throw new KeyNotFoundException($"Item template not found: {itemName}");
        }

        /// Usage:
        /*  var rarityProbabilities = new Dictionary<ItemRarity, int>
            {
                { ItemRarity.Common, 50 },     // 50% chance
                { ItemRarity.Uncommon, 30 },   // 30% chance
                { ItemRarity.Rare, 15 },       // 15% chance
                { ItemRarity.Legendary, 5 }    // 5% chance
            };

            var itemRepo = new ItemRepository();
            var randomItem = itemRepo.GenerateRandomItem(rarityProbabilities);
        */
        public Item GenerateRandomItem(Dictionary<ItemRarity, int> rarityProbabilities)
        {
            // Validate probabilities
            if (rarityProbabilities.Values.Sum() != 100)
            {
                throw new ArgumentException("Rarity probabilities must sum to 100");
            }

            // Generate random number between 0 and 100
            var roll = _random.Next(1, 101);
            var currentThreshold = 0;

            // Determine which rarity we hit
            ItemRarity selectedRarity = ItemRarity.Common;
            foreach (var probability in rarityProbabilities)
            {
                currentThreshold += probability.Value;
                if (roll <= currentThreshold)
                {
                    selectedRarity = probability.Key;
                    break;
                }
            }

            // Get random item from selected rarity
            var possibleItems = _itemsByRarity[selectedRarity];
            if (possibleItems.Count == 0)
            {
                // Fallback to common if no items of selected rarity
                possibleItems = _itemsByRarity[ItemRarity.Common];
            }

            var randomItemName = possibleItems[_random.Next(possibleItems.Count)];
            return CreateItem(randomItemName);
        }
    }
}