using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Decal.Adapter;
using Decal.Adapter.Wrappers;
using Decal.Filters;
using Mag.Shared.Constants;

namespace MosswartMassacre
{
    /// <summary>
    /// Data management class for Flag Tracker
    /// Ported from UBS Lua flagtracker data structures
    /// </summary>
    public class FlagTrackerData : IDisposable
    {
        public FlagTrackerData()
        {
            InitializeDataStructures();
        }
        #region Augmentation Data Structures
        public class AugmentationInfo
        {
            public string Name { get; set; }
            public int? IntId { get; set; }
            public int Repeatable { get; set; }
            public string Trainer { get; set; }
            public string Location { get; set; }
            public int CurrentValue { get; set; }
            public bool IsMaxed => CurrentValue >= Repeatable;
        }

        public Dictionary<string, List<AugmentationInfo>> AugmentationCategories { get; private set; }

        #endregion

        #region Luminance Aura Data Structures
        public class LuminanceAuraInfo
        {
            public string Name { get; set; }
            public int IntId { get; set; }
            public int Cap { get; set; }
            public string QuestFlag { get; set; } // For Seer auras only
            public int CurrentValue { get; set; }
        }

        public Dictionary<string, List<LuminanceAuraInfo>> LuminanceAuraCategories { get; private set; }
        #endregion

        #region Recall Spell Data Structures
        public class RecallSpellInfo
        {
            public string Name { get; set; }
            public int SpellId { get; set; }
            public bool IsKnown { get; set; }
            public int IconId { get; set; }
            public string Category { get; set; }
        }

        public List<RecallSpellInfo> RecallSpells { get; private set; }
        #endregion

        #region Society Quest Data Structures
        public class SocietyQuestInfo
        {
            public string Name { get; set; }
            public string StartTag { get; set; }
            public string EndTag { get; set; }
            public QuestType Type { get; set; }
            public object[] ExtraData { get; set; } // For type-specific data
        }

        public enum QuestType
        {
            Other = 0,
            KillTask = 1,
            CollectItem = 2,
            QuestTag = 3,
            MultiQuestTag = 4
        }

        public Dictionary<string, List<SocietyQuestInfo>> SocietyQuests { get; private set; }
        #endregion

        #region Character Flag Data Structures
        public class CharacterFlagInfo
        {
            public string Name { get; set; }
            public string QuestFlag { get; set; }
            public QuestInfoType InfoType { get; set; }
        }

        public enum QuestInfoType
        {
            SolveCount = 1,
            ReadyCheck = 2,
            StampCheck = 3
        }

        public Dictionary<string, List<CharacterFlagInfo>> CharacterFlags { get; private set; }
        #endregion

        #region Cantrip Data Structures
        public class CantripInfo
        {
            public string Name { get; set; }
            public string Value { get; set; } // "Minor", "Major", "Epic", etc.
            public System.Drawing.Color Color { get; set; }
            public int? IconId { get; set; } // Skill icon from character skills
            public int? SpellIconId { get; set; } // Spell icon (for attributes)
            public int? BackgroundIconId { get; set; } // Background icon (for attributes)
            public int ComputedIconId { get; set; } // Final resolved icon for display
        }

        public Dictionary<string, Dictionary<string, CantripInfo>> Cantrips { get; private set; }
        
        // Skill name mappings for cantrips that have different names than their skills
        private readonly Dictionary<int, string> SkillCantripReplacements = new Dictionary<int, string>
        {
            [15] = "MagicResistance",     // MagicDefense
            [6] = "Invulnerability",      // MeleeDefense  
            [7] = "Impgrenability",       // MissileDefense
            [47] = "MissileWeapon",       // MissileWeapons
            [44] = "HeavyWeapon",         // HeavyWeapons
            [45] = "LightWeapon",         // LightWeapons
            [46] = "FinesseWeapon"        // FinesseWeapons
        };
        #endregion

        #region Weapon Data Structures (Legacy - to be removed)
        // Old weapon structure - keeping for compatibility but unused
        #endregion

        #region Cached Data
        private DateTime lastUpdateTime = DateTime.MinValue;
        private Dictionary<string, object> cachedValues = new Dictionary<string, object>();
        #endregion

        #region Initialization
        private void InitializeDataStructures()
        {
            InitializeAugmentationData();
            InitializeLuminanceAuraData();
            InitializeRecallSpellData();
            InitializeSocietyQuestData();
            InitializeCharacterFlagData();
            InitializeCantripData();
            InitializeNewWeaponData();
        }

        private void InitializeAugmentationData()
        {
            AugmentationCategories = new Dictionary<string, List<AugmentationInfo>>
            {
                ["Death Augs"] = new List<AugmentationInfo>
                {
                    new AugmentationInfo { Name = "Keep Items", IntId = 231, Repeatable = 3, Trainer = "Rohula bint Ludun", Location = "Ayan Baqur" }, // AugmentationLessDeathItemLoss
                    new AugmentationInfo { Name = "Keep Spells", IntId = 232, Repeatable = 1, Trainer = "Erik Festus", Location = "Ayan Baqur" } // AugmentationSpellsRemainPastDeath
                },
                ["Skill Augs"] = new List<AugmentationInfo>
                {
                    new AugmentationInfo { Name = "+5 All Skills", IntId = 326, Repeatable = 1, Trainer = "Arianna the Adept", Location = "Bandit Castle" }, // AugmentationJackOfAllTrades
                    new AugmentationInfo { Name = "+10 Melee Skills", IntId = 300, Repeatable = 1, Trainer = "Carlito Gallo", Location = "Silyun" }, // AugmentationSkilledMelee
                    new AugmentationInfo { Name = "+10 Magic Skills", IntId = 302, Repeatable = 1, Trainer = "Rahina bint Zalanis", Location = "Zaikhal" }, // AugmentationSkilledMagic
                    new AugmentationInfo { Name = "+10 Missile Skills", IntId = 301, Repeatable = 1, Trainer = "Kilaf", Location = "Zaikhal" } // AugmentationSkilledMissile
                },
                ["Rating Augs"] = new List<AugmentationInfo>
                {
                    new AugmentationInfo { Name = "25% Crit Protection", IntId = 233, Repeatable = 1, Trainer = "Piersanti Linante", Location = "Sanamar" }, // AugmentationCriticalDefense
                    new AugmentationInfo { Name = "1% Critical Chance", IntId = 298, Repeatable = 1, Trainer = "Anfram Mellow", Location = "Ayan Baqur" }, // AugmentationCriticalExpertise
                    new AugmentationInfo { Name = "3% Critical Damage", IntId = 299, Repeatable = 1, Trainer = "Alishia bint Aldan", Location = "Ayan Baqur" }, // AugmentationCriticalPower
                    new AugmentationInfo { Name = "3% Damage Rating", IntId = 309, Repeatable = 1, Trainer = "Neela Nashua", Location = "Bandit Castle" }, // AugmentationDamageBonus
                    new AugmentationInfo { Name = "3% Damage Reduction", IntId = 310, Repeatable = 1, Trainer = "Emily Yarow", Location = "Cragstone" } // AugmentationDamageReduction
                },
                ["Burden / Pack Augs"] = new List<AugmentationInfo>
                {
                    new AugmentationInfo { Name = "Extra Carrying Capacity", IntId = 230, Repeatable = 5, Trainer = "Husoon", Location = "Zaikhal" }, // AugmentationIncreasedCarryingCapacity
                    new AugmentationInfo { Name = "Extra Pack Slot", IntId = 229, Repeatable = 1, Trainer = "Dumida bint Ruminre", Location = "Zaikhal" }, // AugmentationExtraPackSlot
                    new AugmentationInfo { Name = "Infused War Magic", IntId = 297, Repeatable = 1, Trainer = "Raphel Detante", Location = "Silyun" }, // AugmentationInfusedWarMagic
                    new AugmentationInfo { Name = "Infused Void Magic", IntId = 328, Repeatable = 1, Trainer = "Morathe", Location = "Candeth Keep" }, // AugmentationInfusedVoidMagic
                    new AugmentationInfo { Name = "Infused Creature Magic", IntId = 294, Repeatable = 1, Trainer = "Gustuv Lansdown", Location = "Cragstone" }, // AugmentationInfusedCreatureMagic
                    new AugmentationInfo { Name = "Infused Life Magic", IntId = 296, Repeatable = 1, Trainer = "Akemi Fei", Location = "Hebian-To" }, // AugmentationInfusedLifeMagic
                    new AugmentationInfo { Name = "Infused Item Magic", IntId = 295, Repeatable = 1, Trainer = "Gan Fo", Location = "Hebian-To" } // AugmentationInfusedItemMagic
                },
                ["Misc Augs"] = new List<AugmentationInfo>
                {
                    new AugmentationInfo { Name = "10% Health Increase", IntId = null, Repeatable = 1, Trainer = "Donatello Linante", Location = "Silyun" }, // No specific property
                    new AugmentationInfo { Name = "Increased Spell Duration", IntId = 238, Repeatable = 5, Trainer = "Nawamara Ujio", Location = "Mayoi" }, // AugmentationIncreasedSpellDuration
                    new AugmentationInfo { Name = "Faster HP Regen", IntId = 237, Repeatable = 2, Trainer = "Alison Dulane", Location = "Bandit Castle" }, // AugmentationFasterRegen
                    new AugmentationInfo { Name = "5% Experience Increase", IntId = 234, Repeatable = 1, Trainer = "Rickard Dumalia", Location = "Silyun" } // AugmentationBonusXp
                },
                ["Salvage Augs"] = new List<AugmentationInfo>
                {
                    new AugmentationInfo { Name = "Specialized Weapon Tinkering", IntId = 228, Repeatable = 1, Trainer = "Lenor Turk", Location = "Cragstone" }, // AugmentationSpecializeWeaponTinkering
                    new AugmentationInfo { Name = "Specialized Armor Tinkering", IntId = 226, Repeatable = 1, Trainer = "Joshun Felden", Location = "Cragstone" }, // AugmentationSpecializeArmorTinkering
                    new AugmentationInfo { Name = "Specialized Item Tinkering", IntId = 225, Repeatable = 1, Trainer = "Brienne Carlus", Location = "Cragstone" }, // AugmentationSpecializeItemTinkering
                    new AugmentationInfo { Name = "Specialized Magic Item Tinkering", IntId = 227, Repeatable = 1, Trainer = "Burrell Sammrun", Location = "Cragstone" }, // AugmentationSpecializeMagicItemTinkering
                    new AugmentationInfo { Name = "Specialized Salvaging", IntId = 224, Repeatable = 1, Trainer = "Robert Crow", Location = "Cragstone" }, // AugmentationSpecializeSalvaging
                    new AugmentationInfo { Name = "25% More Salvage", IntId = 235, Repeatable = 4, Trainer = "Kris Cennis", Location = "Cragstone" }, // AugmentationBonusSalvage
                    new AugmentationInfo { Name = "5% Imbue Chance", IntId = 236, Repeatable = 1, Trainer = "Lug", Location = "Oolutanga's Refuge" } // AugmentationBonusImbueChance
                },
                ["Stat Augs"] = new List<AugmentationInfo>
                {
                    new AugmentationInfo { Name = "All Stats", IntId = 217, Repeatable = 10, Trainer = "", Location = "" }, // AugmentationInnateFamily
                    new AugmentationInfo { Name = "Strength", IntId = 218, Repeatable = 10, Trainer = "Fiun Luunere", Location = "Fiun Outpost" }, // AugmentationInnateStrength
                    new AugmentationInfo { Name = "Endurance", IntId = 219, Repeatable = 10, Trainer = "Fiun Ruun", Location = "Fiun Outpost" }, // AugmentationInnateEndurance
                    new AugmentationInfo { Name = "Coordination", IntId = 220, Repeatable = 10, Trainer = "Fiun Bayaas", Location = "Fiun Outpost" }, // AugmentationInnateCoordination
                    new AugmentationInfo { Name = "Quickness", IntId = 221, Repeatable = 10, Trainer = "Fiun Riish", Location = "Fiun Outpost" }, // AugmentationInnateQuickness
                    new AugmentationInfo { Name = "Focus", IntId = 222, Repeatable = 10, Trainer = "Fiun Vasherr", Location = "Fiun Outpost" }, // AugmentationInnateFocus
                    new AugmentationInfo { Name = "Self", IntId = 223, Repeatable = 10, Trainer = "Fiun Noress", Location = "Fiun Outpost" } // AugmentationInnateSelf
                },
                ["Resistance Augs"] = new List<AugmentationInfo>
                {
                    new AugmentationInfo { Name = "All Resistances", IntId = 239, Repeatable = 2, Trainer = "", Location = "" }, // AugmentationResistanceFamily
                    new AugmentationInfo { Name = "Blunt", IntId = 242, Repeatable = 2, Trainer = "Nawamara Dia", Location = "Hebian-To" }, // AugmentationResistanceBlunt
                    new AugmentationInfo { Name = "Pierce", IntId = 241, Repeatable = 2, Trainer = "Kyujo Rujen", Location = "Hebian-To" }, // AugmentationResistancePierce
                    new AugmentationInfo { Name = "Slashing", IntId = 240, Repeatable = 2, Trainer = "Ilin Wis", Location = "Hebian-To" }, // AugmentationResistanceSlash
                    new AugmentationInfo { Name = "Fire", IntId = 244, Repeatable = 2, Trainer = "Rikshen Ri", Location = "Hebian-To" }, // AugmentationResistanceFire
                    new AugmentationInfo { Name = "Frost", IntId = 245, Repeatable = 2, Trainer = "Lu Bao", Location = "Hebian-To" }, // AugmentationResistanceFrost
                    new AugmentationInfo { Name = "Acid", IntId = 243, Repeatable = 2, Trainer = "Shujio Milao", Location = "Hebian-To" }, // AugmentationResistanceAcid
                    new AugmentationInfo { Name = "Lightning", IntId = 246, Repeatable = 2, Trainer = "Enli Yuo", Location = "Hebian-To" } // AugmentationResistanceLightning
                }
            };
        }

        private void InitializeLuminanceAuraData()
        {
            LuminanceAuraCategories = new Dictionary<string, List<LuminanceAuraInfo>>
            {
                ["Nalicana Auras"] = new List<LuminanceAuraInfo>
                {
                    new LuminanceAuraInfo { Name = "+1 Aetheria Proc Rating", IntId = 338, Cap = 5 }, // LumAugSurgeChanceRating
                    new LuminanceAuraInfo { Name = "+1 Damage Reduction Rating", IntId = 334, Cap = 5 }, // LumAugDamageReductionRating
                    new LuminanceAuraInfo { Name = "+1 Crit Reduction Rating", IntId = 336, Cap = 5 }, // LumAugCritReductionRating
                    new LuminanceAuraInfo { Name = "+1 Damage Rating", IntId = 333, Cap = 5 }, // LumAugDamageRating
                    new LuminanceAuraInfo { Name = "+1 Crit Damage Rating", IntId = 335, Cap = 5 }, // LumAugCritDamageRating
                    new LuminanceAuraInfo { Name = "+1 Heal Rating", IntId = 342, Cap = 5 }, // LumAugHealingRating
                    new LuminanceAuraInfo { Name = "+1 Equipment Mana Rating", IntId = 339, Cap = 5 }, // LumAugItemManaUsage
                    new LuminanceAuraInfo { Name = "+1 Mana Stone Rating", IntId = 340, Cap = 5 }, // LumAugItemManaGain
                    new LuminanceAuraInfo { Name = "+1 Crafting Skills", IntId = 343, Cap = 5 }, // LumAugSkilledCraft
                    new LuminanceAuraInfo { Name = "+1 All Skills", IntId = 365, Cap = 10 } // LumAugAllSkills
                },
                ["Seer Auras"] = new List<LuminanceAuraInfo>
                {
                    new LuminanceAuraInfo { Name = "(Ka'hiri) +2 Specialized Skills", IntId = 344, Cap = 5, QuestFlag = "LoyalToKahiri" }, // LumAugSkilledSpec
                    new LuminanceAuraInfo { Name = "(Ka'hiri) +1 Damage Rating", IntId = 333, Cap = 5, QuestFlag = "LoyalToKahiri" }, // LumAugDamageRating
                    new LuminanceAuraInfo { Name = "(Shade of Lady Adja) +2 Specialized Skills", IntId = 344, Cap = 5, QuestFlag = "LoyalToShadeOfLadyAdja" }, // LumAugSkilledSpec
                    new LuminanceAuraInfo { Name = "(Shade of Lady Adja) +1 Damage Reduction Rating", IntId = 334, Cap = 5, QuestFlag = "LoyalToShadeOfLadyAdja" }, // LumAugDamageReductionRating
                    new LuminanceAuraInfo { Name = "(Liam of Gelid) +1 Damage Rating", IntId = 333, Cap = 5, QuestFlag = "LoyalToLiamOfGelid" }, // LumAugDamageRating
                    new LuminanceAuraInfo { Name = "(Liam of Gelid) +1 Crit Damage Rating", IntId = 335, Cap = 5, QuestFlag = "LoyalToLiamOfGelid" }, // LumAugCritDamageRating
                    new LuminanceAuraInfo { Name = "(Lord Tyragar) +1 Crit Reduction Rating", IntId = 336, Cap = 5, QuestFlag = "LoyalToLordTyragar" }, // LumAugCritReductionRating
                    new LuminanceAuraInfo { Name = "(Lord Tyragar) +1 Damage Reduction Rating", IntId = 334, Cap = 5, QuestFlag = "LoyalToLordTyragar" } // LumAugDamageReductionRating
                }
            };
        }

        private void InitializeRecallSpellData()
        {
            RecallSpells = new List<RecallSpellInfo>
            {
                new RecallSpellInfo { Name = "Recall the Sanctuary", SpellId = 2023, IconId = 0, Category = "Basic Recalls" },
                new RecallSpellInfo { Name = "Aerlinthe Recall", SpellId = 2041, IconId = 0, Category = "Island Recalls" },
                new RecallSpellInfo { Name = "Mount Lethe Recall", SpellId = 2813, IconId = 0, Category = "Island Recalls" },
                new RecallSpellInfo { Name = "Recall Aphus Lassel", SpellId = 2931, IconId = 0, Category = "Island Recalls" },
                new RecallSpellInfo { Name = "Ulgrim's Recall", SpellId = 2941, IconId = 0, Category = "Special Recalls" },
                new RecallSpellInfo { Name = "Recall to the Singularity Caul", SpellId = 2943, IconId = 0, Category = "Island Recalls" },
                new RecallSpellInfo { Name = "Glenden Wood Recall", SpellId = 3865, IconId = 0, Category = "Town Recalls" },
                new RecallSpellInfo { Name = "Bur Recall", SpellId = 4084, IconId = 0, Category = "Town Recalls" },
                new RecallSpellInfo { Name = "Call of the Mhoire Forge", SpellId = 4128, IconId = 0, Category = "Special Recalls" },
                new RecallSpellInfo { Name = "Paradox-touched Olthoi Infested Area Recall", SpellId = 4198, IconId = 0, Category = "Special Recalls" },
                new RecallSpellInfo { Name = "Colosseum Recall", SpellId = 4213, IconId = 0, Category = "Special Recalls" },
                new RecallSpellInfo { Name = "Return to the Keep", SpellId = 4214, IconId = 0, Category = "Special Recalls" },
                new RecallSpellInfo { Name = "Gear Knight Invasion Area Camp Recall", SpellId = 5330, IconId = 0, Category = "Special Recalls" },
                new RecallSpellInfo { Name = "Lost City of Neftet Recall", SpellId = 5541, IconId = 0, Category = "Special Recalls" },
                new RecallSpellInfo { Name = "Rynthid Recall", SpellId = 6150, IconId = 0, Category = "Special Recalls" },
                new RecallSpellInfo { Name = "Viridian Rise Recall", SpellId = 6321, IconId = 0, Category = "Special Recalls" },
                new RecallSpellInfo { Name = "Viridian Rise Great Tree Recall", SpellId = 6322, IconId = 0, Category = "Special Recalls" }
            };
        }

        private void InitializeSocietyQuestData()
        {
            SocietyQuests = new Dictionary<string, List<SocietyQuestInfo>>();
            // TODO: Initialize society quest data from Lua
        }

        private void InitializeCharacterFlagData()
        {
            CharacterFlags = new Dictionary<string, List<CharacterFlagInfo>>
            {
                ["Additional Skill Credits"] = new List<CharacterFlagInfo>
                {
                    new CharacterFlagInfo { Name = "+1 Skill Lum Aura", QuestFlag = "lumaugskillquest", InfoType = QuestInfoType.SolveCount },
                    new CharacterFlagInfo { Name = "+1 Skill Aun Ralirea", QuestFlag = "arantahkill1", InfoType = QuestInfoType.SolveCount },
                    new CharacterFlagInfo { Name = "+1 Skill Chasing Oswald", QuestFlag = "oswaldmanualcompleted", InfoType = QuestInfoType.SolveCount }
                },
                ["Aetheria"] = new List<CharacterFlagInfo>
                {
                    new CharacterFlagInfo { Name = "Blue Aetheria (75)", QuestFlag = "efulcentermanafieldused", InfoType = QuestInfoType.StampCheck },
                    new CharacterFlagInfo { Name = "Yellow Aetheria (150)", QuestFlag = "efmlcentermanafieldused", InfoType = QuestInfoType.StampCheck },
                    new CharacterFlagInfo { Name = "Red Aetheria (225)", QuestFlag = "efllcentermanafieldused", InfoType = QuestInfoType.StampCheck }
                }
                // TODO: Add remaining character flag categories
            };
        }

        private void InitializeCantripData()
        {
            Cantrips = new Dictionary<string, Dictionary<string, CantripInfo>>
            {
                ["Specialized Skills"] = new Dictionary<string, CantripInfo>(),  // Dynamically populated
                ["Trained Skills"] = new Dictionary<string, CantripInfo>(),      // Dynamically populated
                ["Attributes"] = new Dictionary<string, CantripInfo>(), // Dynamically populated when cantrips are detected
                ["Protection Auras"] = new Dictionary<string, CantripInfo>
                {
                    // Pre-populate all protection auras so they show as red when missing
                    ["Armor"] = new CantripInfo { Name = "Armor", Value = "N/A", Color = System.Drawing.Color.White },
                    ["Bludgeoning Ward"] = new CantripInfo { Name = "Bludgeoning Ward", Value = "N/A", Color = System.Drawing.Color.White },
                    ["Piercing Ward"] = new CantripInfo { Name = "Piercing Ward", Value = "N/A", Color = System.Drawing.Color.White },
                    ["Slashing Ward"] = new CantripInfo { Name = "Slashing Ward", Value = "N/A", Color = System.Drawing.Color.White },
                    ["Flame Ward"] = new CantripInfo { Name = "Flame Ward", Value = "N/A", Color = System.Drawing.Color.White },
                    ["Frost Ward"] = new CantripInfo { Name = "Frost Ward", Value = "N/A", Color = System.Drawing.Color.White },
                    ["Acid Ward"] = new CantripInfo { Name = "Acid Ward", Value = "N/A", Color = System.Drawing.Color.White },
                    ["Storm Ward"] = new CantripInfo { Name = "Storm Ward", Value = "N/A", Color = System.Drawing.Color.White }
                }
            };
        }

        #endregion

        #region Refresh Methods
        public void RefreshAll()
        {
            RefreshCachedData();
            RefreshAugmentations();
            RefreshLuminanceAuras();
            RefreshRecallSpells();
            RefreshSocietyQuests();
            RefreshFacilityHubQuests();
            RefreshCharacterFlags();
            RefreshCantrips();
        }

        public void RefreshCachedData()
        {
            try
            {
                if (CoreManager.Current?.CharacterFilter?.Name != null)
                {
                    // Update cached values
                    var character = CoreManager.Current.CharacterFilter;
                    lastUpdateTime = DateTime.Now;
                    
                    // TODO: Implement cached data refresh
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error refreshing cached data: {ex.Message}");
            }
        }

        public void RefreshAugmentations()
        {
            try
            {
                if (CoreManager.Current?.CharacterFilter?.Name == null) return;
                
                var character = CoreManager.Current.CharacterFilter;
                
                // Update augmentation values
                foreach (var category in AugmentationCategories)
                {
                    foreach (var aug in category.Value)
                    {
                        if (aug.IntId.HasValue)
                        {
                            // Get augmentation value from character data using DECAL API
                            try
                            {
                                if (CoreManager.Current?.CharacterFilter != null)
                                {
                                    var characterFilter = CoreManager.Current.CharacterFilter;
                                    var playerObject = CoreManager.Current.WorldFilter[characterFilter.Id];
                                    
                                    if (playerObject != null)
                                    {
                                        // Use CharacterFilter.GetCharProperty for character properties
                                        try
                                        {
                                            // DECAL API uses CharacterFilter.GetCharProperty for character properties
                                            aug.CurrentValue = characterFilter.GetCharProperty(aug.IntId.Value);
                                        }
                                        catch
                                        {
                                            // Try alternative access using reflection
                                            try
                                            {
                                                var valuesMethod = playerObject.GetType().GetMethod("Values", new Type[] { typeof(int) });
                                                if (valuesMethod != null)
                                                {
                                                    aug.CurrentValue = (int)valuesMethod.Invoke(playerObject, new object[] { aug.IntId.Value });
                                                }
                                                else
                                                {
                                                    aug.CurrentValue = 0;
                                                }
                                            }
                                            catch
                                            {
                                                aug.CurrentValue = 0;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        aug.CurrentValue = 0;
                                    }
                                }
                                else
                                {
                                    aug.CurrentValue = 0;
                                }
                            }
                            catch
                            {
                                aug.CurrentValue = 0;
                            }
                        }
                        else
                        {
                            // Handle special case for Asheron's Lesser Benediction (inventory count)
                            if (aug.Name == "Asheron's Lesser Benediction")
                            {
                                // Count Asheron's Lesser Benediction items in inventory
                                aug.CurrentValue = CountAsheronsLesserBenediction();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error refreshing augmentations: {ex.Message}");
            }
        }

        private int CountAsheronsLesserBenediction()
        {
            try
            {
                int count = 0;
                
                // Search inventory for Asheron's Lesser Benediction
                foreach (WorldObject item in CoreManager.Current.WorldFilter.GetInventory())
                {
                    if (item.Name.Contains("Asheron's Lesser Benediction"))
                    {
                        // Use stack size for item count (default to 1 for non-stackable items)
                        try
                        {
                            // Access stack size using reflection to avoid type issues
                            var stackMethod = item.GetType().GetMethod("Values", new Type[] { typeof(int) });
                            if (stackMethod != null)
                            {
                                int stackSize = (int)stackMethod.Invoke(item, new object[] { 12 }); // 12 = StackSize
                                count += Math.Max(1, stackSize);
                            }
                            else
                            {
                                count += 1; // Default to 1
                            }
                        }
                        catch
                        {
                            count += 1; // Default fallback
                        }
                    }
                }
                
                return count;
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error counting Asheron's Lesser Benediction: {ex.Message}");
                return 0;
            }
        }

        public void RefreshLuminanceAuras()
        {
            try
            {
                if (CoreManager.Current?.CharacterFilter?.Name == null) return;
                
                var characterFilter = CoreManager.Current.CharacterFilter;
                
                // Update luminance aura values
                foreach (var category in LuminanceAuraCategories)
                {
                    foreach (var aura in category.Value)
                    {
                        try
                        {
                            // Use CharacterFilter.GetCharProperty for luminance auras
                            aura.CurrentValue = characterFilter.GetCharProperty(aura.IntId);
                        }
                        catch
                        {
                            aura.CurrentValue = 0;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error refreshing luminance auras: {ex.Message}");
            }
        }

        public void RefreshRecallSpells()
        {
            try
            {
                if (CoreManager.Current?.CharacterFilter?.Name == null) return;
                
                var characterFilter = CoreManager.Current.CharacterFilter;
                int knownCount = 0;
                
                // Check each recall spell to see if the character knows it
                foreach (var recall in RecallSpells)
                {
                    try
                    {
                        // Use DECAL API to check if the character knows this spell
                        recall.IsKnown = characterFilter.IsSpellKnown(recall.SpellId);
                        if (recall.IsKnown) knownCount++;
                        
                        // Get spell icon from FileService if not already set
                        if (recall.IconId == 0)
                        {
                            recall.IconId = GetSpellIcon(recall.SpellId);
                        }
                    }
                    catch
                    {
                        recall.IsKnown = false;
                    }
                }
                
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error refreshing recall spells: {ex.Message}");
            }
        }
        
        private int GetSpellIcon(int spellId)
        {
            try
            {
                // Try to get real spell icon first (matches original Lua approach)
                int realSpellIcon = GetRealSpellIcon(spellId);
                if (realSpellIcon != 0)
                {
                    return realSpellIcon;
                }
                
                // Fallback to known recall spell icons
                var recallSpellIcons = new Dictionary<int, int>
                {
                    // Recall spell icons from AC spell data
                    [2023] = 2943,  // Recall the Sanctuary
                    [2041] = 2814,  // Aerlinthe Recall
                    [2813] = 2813,  // Mount Lethe Recall
                    [2931] = 2931,  // Recall Aphus Lassel
                    [2943] = 2943,  // Recall to the Singularity Caul
                    [3865] = 3864,  // Glenden Wood Recall
                    [4084] = 4084,  // Bur Recall
                    [2941] = 2814,  // Ulgrim's Recall (uses portal icon)
                    [4128] = 4128,  // Call of the Mhoire Forge
                    [4198] = 4197,  // Paradox-touched Olthoi Infested Area Recall
                    [4213] = 4213,  // Colosseum Recall
                    [4214] = 4199,  // Return to the Keep
                    [5330] = 5175,  // Gear Knight Invasion Area Camp Recall
                    [5541] = 5541,  // Lost City of Neftet Recall
                    [6150] = 6150,  // Rynthid Recall
                    [6321] = 6321,  // Viridian Rise Recall
                    [6322] = 6322   // Viridian Rise Great Tree Recall
                };
                
                if (recallSpellIcons.ContainsKey(spellId))
                {
                    // Add offset for spell icons
                    return recallSpellIcons[spellId] + 0x6000000;
                }
                
                // Final fallback - default portal/recall icon
                return 0x6002D14;
            }
            catch
            {
                return 0x6002D14; // Default icon on error
            }
        }
        
        private int GetRealSpellIcon(int spellId)
        {
            try
            {
                // Method 1: Use DECAL FileService SpellTable directly (proper API approach)
                try
                {
                    var fileService = CoreManager.Current.Filter<Decal.Filters.FileService>();
                    if (fileService?.SpellTable != null)
                    {
                        var spell = fileService.SpellTable.GetById(spellId);
                        if (spell != null)
                        {
                            // Use reflection to access the internal Spell_Class object
                            // DECAL's Spell wrapper has an internal m_pSpell field that contains the actual data
                            var spellType = spell.GetType();
                            
                            // Try to get the internal spell object first
                            var internalSpellField = spellType.GetField("m_pSpell", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                            if (internalSpellField != null)
                            {
                                var internalSpell = internalSpellField.GetValue(spell);
                                if (internalSpell != null)
                                {
                                    // Now get the icon from the internal spell object
                                    var internalType = internalSpell.GetType();
                                    
                                    // Try icon properties on the internal object
                                    string[] iconPropertyNames = { "Icon", "icon", "IconId", "iconId", "IconID", "iconID" };
                                    foreach (var propName in iconPropertyNames)
                                    {
                                        try
                                        {
                                            // Try as property
                                            var iconProperty = internalType.GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                                            if (iconProperty != null)
                                            {
                                                var iconValue = iconProperty.GetValue(internalSpell, null);
                                                if (iconValue is int iconInt && iconInt > 0)
                                                {
                                                    // Spell icons use raw values (no offset)
                                                    return iconInt;
                                                }
                                                else if (iconValue is uint iconUint && iconUint > 0)
                                                {
                                                    return (int)iconUint;
                                                }
                                            }
                                            
                                            // Try as field
                                            var iconField = internalType.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                                            if (iconField != null)
                                            {
                                                var iconValue = iconField.GetValue(internalSpell);
                                                if (iconValue is int iconInt && iconInt > 0)
                                                {
                                                    return iconInt;
                                                }
                                                else if (iconValue is uint iconUint && iconUint > 0)
                                                {
                                                    return (int)iconUint;
                                                }
                                            }
                                        }
                                        catch
                                        {
                                            // Continue trying other property names
                                        }
                                    }
                                }
                            }
                            
                            // Fallback: Try direct properties on the wrapper
                            string[] wrapperPropertyNames = { "Icon", "IconId", "IconID" };
                            foreach (var propName in wrapperPropertyNames)
                            {
                                var iconProperty = spellType.GetProperty(propName, BindingFlags.Public | BindingFlags.Instance);
                                if (iconProperty != null)
                                {
                                    var iconValue = iconProperty.GetValue(spell, null);
                                    if (iconValue is int iconId && iconId > 0)
                                    {
                                        return iconId;
                                    }
                                }
                            }
                        }
                    }
                }
                catch
                {
                }
                
                // Method 2: Use known spell icon mappings for cantrips
                // These are based on AC spell icon IDs from spell data
                var cantripSpellIcons = new Dictionary<int, int>
                {
                    // Strength cantrips - use Strength Self VIII icon
                    [2091] = 1332,  // Major Strength
                    [4325] = 1332,  // Epic Strength
                    [6107] = 1332,  // Legendary Strength
                    
                    // Endurance cantrips - use Endurance Self VIII icon
                    [2061] = 1354,  // Major Endurance
                    [4226] = 1354,  // Epic Endurance
                    [6104] = 1354,  // Legendary Endurance
                    
                    // Coordination cantrips - use Coordination Self VIII icon
                    [2059] = 1378,  // Major Coordination
                    [4296] = 1378,  // Epic Coordination
                    [6102] = 1378,  // Legendary Coordination
                    
                    // Quickness cantrips - use Quickness Self VIII icon
                    [2081] = 1409,  // Major Quickness
                    [4319] = 1409,  // Epic Quickness
                    [6106] = 1409,  // Legendary Quickness
                    
                    // Focus cantrips - use Focus Self VIII icon
                    [2067] = 1426,  // Major Focus
                    [4304] = 1426,  // Epic Focus
                    [6105] = 1426,  // Legendary Focus
                    
                    // Willpower/Self cantrips - use Willpower Self VIII icon
                    [2091] = 1450,  // Major Willpower
                    [4329] = 1450,  // Epic Willpower
                    [6101] = 1450,  // Legendary Willpower
                    
                    // Protection Auras - Armor - use Armor Self VIII icon
                    [2113] = 1316,  // Major Armor
                    [4291] = 1316,  // Epic Armor
                    [6095] = 1316,  // Legendary Armor
                    
                    // Protection Auras - Physical
                    [2245] = 1023,  // Major Piercing Ward - use Blade Protection Self VIII
                    [4306] = 1023,  // Epic Piercing Ward
                    [6096] = 1023,  // Legendary Piercing Ward
                    
                    [2244] = 1114,  // Major Slashing Ward - use Piercing Protection Self VIII  
                    [4321] = 1114,  // Epic Slashing Ward
                    [6097] = 1114,  // Legendary Slashing Ward
                    
                    [2243] = 1138,  // Major Bludgeoning Ward - use Bludgeoning Protection Self VIII
                    [4293] = 1138,  // Epic Bludgeoning Ward
                    [6098] = 1138,  // Legendary Bludgeoning Ward
                    
                    // Protection Auras - Elemental
                    [2157] = 1096,  // Major Frost Ward - use Cold Protection Self VIII
                    [4309] = 1096,  // Epic Frost Ward
                    [6100] = 1096,  // Legendary Frost Ward
                    
                    [2158] = 1035,  // Major Flame Ward - use Fire Protection Self VIII
                    [4294] = 1035,  // Epic Flame Ward
                    [6099] = 1035,  // Legendary Flame Ward
                    
                    [2149] = 1078,  // Major Acid Ward - use Acid Protection Self VIII
                    [4290] = 1078,  // Epic Acid Ward
                    [6094] = 1078,  // Legendary Acid Ward
                    
                    [2159] = 1161,  // Major Storm Ward - use Lightning Protection Self VIII
                    [4322] = 1161,  // Epic Storm Ward
                    [6079] = 1161,  // Legendary Storm Ward
                    
                    // Magic Defense cantrips - use Magic Resistance Self VIII icon
                    [2249] = 610,   // Major Magic Resistance
                    [4314] = 610,   // Epic Magic Resistance
                    [6067] = 610,   // Legendary Magic Resistance
                    
                    // Melee Defense cantrips - use Invulnerability Self VIII icon
                    [2248] = 562,   // Major Invulnerability
                    [4312] = 562,   // Epic Invulnerability
                    [6051] = 562,   // Legendary Invulnerability
                    
                    // Missile Defense cantrips - use Impregnability Self VIII icon
                    [2247] = 1562,  // Major Impregnability
                    [4311] = 1562,  // Epic Impregnability
                    [6055] = 1562,  // Legendary Impregnability
                    
                    // Life Magic cantrips - use Life Magic Mastery Self VIII icon
                    [2156] = 610,   // Major Life Magic Aptitude
                    [4700] = 610,   // Epic Life Magic Aptitude
                    [6044] = 610,   // Legendary Life Magic Aptitude
                    
                    // War Magic cantrips - use War Magic Mastery Self VIII icon
                    [2183] = 634,   // Major War Magic Aptitude
                    [4715] = 634,   // Epic War Magic Aptitude
                    [6075] = 634,   // Legendary War Magic Aptitude
                    
                    // Creature Enchantment cantrips - use Creature Enchantment Mastery Self VIII icon
                    [2215] = 586,   // Major Creature Enchantment Aptitude
                    [4689] = 586,   // Epic Creature Enchantment Aptitude
                    [6042] = 586,   // Legendary Creature Enchantment Aptitude
                    
                    // Item Enchantment cantrips - use Item Enchantment Mastery Self VIII icon
                    [2249] = 658,   // Major Item Enchantment Aptitude
                    [4697] = 658,   // Epic Item Enchantment Aptitude
                    [6043] = 658,   // Legendary Item Enchantment Aptitude
                    
                    // Void Magic cantrips - use Void Magic Mastery Self VI icon (no VIII version)
                    [5427] = 5418,  // Major Void Magic Aptitude
                    [5428] = 5418,  // Epic Void Magic Aptitude
                    [5429] = 5418,  // Legendary Void Magic Aptitude
                    
                    // Weapon cantrips
                    [2223] = 522,   // Major Heavy Weapon Aptitude - use Heavy Weapon Mastery Self VIII
                    [4624] = 522,   // Epic Heavy Weapon Aptitude
                    [6073] = 522,   // Legendary Heavy Weapon Aptitude
                    
                    [2226] = 327,   // Major Light Weapon Aptitude - use Light Weapon Mastery Self VI
                    [4639] = 327,   // Epic Light Weapon Aptitude
                    [6074] = 327,   // Legendary Light Weapon Aptitude
                    
                    [2227] = 350,   // Major Finesse Weapon Aptitude - use Finesse Weapon Mastery Self VI
                    [4638] = 350,   // Epic Finesse Weapon Aptitude
                    [6072] = 350,   // Legendary Finesse Weapon Aptitude
                    
                    [2230] = 473,   // Major Missile Weapon Aptitude - use Missile Weapon Mastery Self VI
                    [4713] = 473,   // Epic Missile Weapon Aptitude
                    [6071] = 473,   // Legendary Missile Weapon Aptitude
                    
                    // Mana Conversion cantrips - use Mana Conversion Mastery Self VIII icon
                    [2152] = 658,   // Major Mana Conversion Prowess
                    [4705] = 658,   // Epic Mana Conversion Prowess
                    [6048] = 658,   // Legendary Mana Conversion Prowess
                };
                
                if (cantripSpellIcons.ContainsKey(spellId))
                {
                    int iconId = cantripSpellIcons[spellId];
                    // Add offset for spell icons to display correctly in VVS
                    // Based on MagTools pattern, spell icons need the offset for display
                    int finalIconId = iconId + 0x6000000;
                    return finalIconId;
                }
                
                return 0; // No real icon found
            }
            catch
            {
                return 0;
            }
        }

        public void RefreshSocietyQuests()
        {
            try
            {
                // TODO: Implement society quest refresh
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error refreshing society quests: {ex.Message}");
            }
        }

        public void RefreshFacilityHubQuests()
        {
            try
            {
                // TODO: Implement facility hub quest refresh
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error refreshing facility hub quests: {ex.Message}");
            }
        }

        public void RefreshCharacterFlags()
        {
            try
            {
                // TODO: Implement character flag refresh
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error refreshing character flags: {ex.Message}");
            }
        }

        public void RefreshCantrips()
        {
            try
            {
                
                if (CoreManager.Current?.CharacterFilter?.Name == null) 
                {
                    return;
                }
                
                var characterFilter = CoreManager.Current.CharacterFilter;
                var playerObject = CoreManager.Current.WorldFilter[characterFilter.Id];
                
                if (playerObject == null) 
                {
                    return;
                }
                
                
                // Clear dynamic skill lists
                Cantrips["Specialized Skills"].Clear();
                Cantrips["Trained Skills"].Clear();
                
                // Populate skills dynamically based on character's actual training
                PopulateCharacterSkills(characterFilter);
                
                // Reset all cantrips to "N/A"
                foreach (var category in Cantrips)
                {
                    foreach (var cantrip in category.Value.Values)
                    {
                        cantrip.Value = "N/A";
                        cantrip.Color = System.Drawing.Color.White;
                    }
                }
                
                // Scan active spells for cantrips using CharacterFilter.Enchantments
                int enchantmentCount = characterFilter.Underlying.EnchantmentCount;
                for (int i = 0; i < enchantmentCount; i++)
                {
                    Decal.Interop.Filters.Enchantment ench = null;
                    try
                    {
                        ench = characterFilter.Underlying.get_Enchantment(i);
                        if (ench == null)
                            continue;

                        var spell = SpellManager.GetSpell(ench.SpellID);
                        if (spell != null && spell.CantripLevel != Mag.Shared.Spells.Spell.CantripLevels.None)
                        {
                            DetectCantrip(ench.SpellID);
                        }
                    }
                    finally
                    {
                        if (ench != null)
                        {
                            Marshal.ReleaseComObject(ench);
                        }
                    }
                }
                
                // Compute final icon IDs for all cantrips after refresh
                foreach (var category in Cantrips)
                {
                    foreach (var cantrip in category.Value.Values)
                    {
                        cantrip.ComputedIconId = ComputeCantripIcon(cantrip);
                    }
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error refreshing cantrips: {ex.Message}");
            }
        }
        
        private void PopulateCharacterSkills(CharacterFilter characterFilter)
        {
            try
            {
                // Map of skill IDs to skill names - based on DECAL CharFilterSkillType enumeration
                // Reference: DECAL API documentation and AC development sources
                var skillIdToName = new Dictionary<int, string>
                {
                    [1] = "Axe",                    // Retired weapon skill
                    [2] = "Bow",                    // Retired weapon skill
                    [3] = "Crossbow",               // Retired weapon skill  
                    [4] = "Dagger",                 // Retired weapon skill
                    [5] = "Mace",                   // Retired weapon skill
                    [6] = "Melee Defense",          // Active defense skill
                    [7] = "Missile Defense",        // Active defense skill
                    [8] = "Sling",                  // Retired weapon skill
                    [9] = "Spear",                  // Retired weapon skill
                    [10] = "Staff",                 // Retired weapon skill
                    [11] = "Sword",                 // Retired weapon skill
                    [12] = "Thrown Weapons",        // Retired weapon skill
                    [13] = "Unarmed Combat",        // Retired weapon skill
                    [14] = "Arcane Lore",           // Active magic skill
                    [15] = "Magic Defense",         // Active defense skill
                    [16] = "Mana Conversion",       // Active magic skill
                    [17] = "Spellcraft",            // Unused/Reserved
                    [18] = "Item Tinkering",        // Active tinker skill
                    [19] = "Assess Person",         // Active misc skill
                    [20] = "Deception",             // Active misc skill
                    [21] = "Healing",               // Active misc skill
                    [22] = "Jump",                  // Active misc skill
                    [23] = "Lockpick",              // Active misc skill
                    [24] = "Run",                   // Active misc skill
                    [25] = "Awareness",             // Unused/Reserved
                    [26] = "Arms and Armor Repair", // Unused/Reserved
                    [27] = "Assess Creature",       // Active misc skill
                    [28] = "Weapon Tinkering",      // Active tinker skill
                    [29] = "Armor Tinkering",       // Active tinker skill
                    [30] = "Magic Item Tinkering",  // Active tinker skill
                    [31] = "Creature Enchantment",  // Active magic skill
                    [32] = "Item Enchantment",      // Active magic skill
                    [33] = "Life Magic",            // Active magic skill
                    [34] = "War Magic",             // Active magic skill
                    [35] = "Leadership",            // Active misc skill
                    [36] = "Loyalty",               // Active misc skill
                    [37] = "Fletching",             // Active tinker skill
                    [38] = "Alchemy",               // Active tinker skill
                    [39] = "Cooking",               // Active tinker skill
                    [40] = "Salvaging",             // Active tinker skill
                    [41] = "Two Handed Combat",     // Active weapon skill
                    [42] = "Gearcraft",             // Retired tinker skill
                    [43] = "Void Magic",            // Active magic skill
                    [44] = "Heavy Weapons",         // Active weapon skill
                    [45] = "Light Weapons",         // Active weapon skill
                    [46] = "Finesse Weapons",       // Active weapon skill
                    [47] = "Missile Weapons",       // Active weapon skill
                    [48] = "Shield",                // Active weapon skill
                    [49] = "Dual Wield",            // Active weapon skill
                    [50] = "Recklessness",          // Active weapon skill
                    [51] = "Sneak Attack",          // Active weapon skill
                    [52] = "Dirty Fighting",        // Active weapon skill
                    [53] = "Threat Assessment",     // Unused/Reserved
                    [54] = "Summoning"              // Active magic skill
                };
                
                // Check each skill's training status
                foreach (var kvp in skillIdToName)
                {
                    int skillId = kvp.Key;
                    string skillName = kvp.Value;
                    
                    try
                    {
                        // Get skill training status using CharacterFilter.Skills
                        var skillInfo = characterFilter.Skills[(Decal.Adapter.Wrappers.CharFilterSkillType)skillId];
                        if (skillInfo == null) continue;
                        
                        // Apply skill name replacements for cantrips
                        if (SkillCantripReplacements.ContainsKey(skillId))
                        {
                            skillName = SkillCantripReplacements[skillId];
                        }
                        
                        if (skillInfo.Training == Decal.Adapter.Wrappers.TrainingType.Specialized)
                        {
                            Cantrips["Specialized Skills"][skillName] = new CantripInfo 
                            { 
                                Name = skillName,
                                Value = "N/A", 
                                Color = System.Drawing.Color.White
                                // IconId removed - will be set by spell icon when cantrips are detected
                            };
                        }
                        else if (skillInfo.Training == Decal.Adapter.Wrappers.TrainingType.Trained)
                        {
                            Cantrips["Trained Skills"][skillName] = new CantripInfo 
                            { 
                                Name = skillName,
                                Value = "N/A", 
                                Color = System.Drawing.Color.White
                                // IconId removed - will be set by spell icon when cantrips are detected
                            };
                        }
                    }
                    catch
                    {
                        // Skill not available on this character, skip it
                    }
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error populating character skills: {ex.Message}");
            }
        }
        
        private int? GetSkillIconId(int skillId)
        {
            try
            {
                var characterFilter = CoreManager.Current.CharacterFilter;
                if (characterFilter == null) 
                {
                    return GetFallbackSkillIcon(skillId);
                }
                
                // Validate skillId range for DECAL API
                if (skillId < 1 || skillId > 54)
                {
                    return GetFallbackSkillIcon(skillId);
                }
                
                try 
                {
                    var skillInfo = characterFilter.Skills[(Decal.Adapter.Wrappers.CharFilterSkillType)skillId];
                    if (skillInfo == null)
                    {
                        return GetFallbackSkillIcon(skillId);
                    }
                    
                    
                    // Try to access skill icon via reflection (DECAL's SkillInfoWrapper.Dat property)
                    var skillType = skillInfo.GetType();
                    
                    // Method 1: Try FileService SkillTable approach (most reliable)
                    int realIconId = GetRealSkillIconFromDat(skillId);
                    if (realIconId > 0)
                    {
                        return realIconId + 0x6000000;
                    }
                    
                    // Method 2: Reflection on SkillInfoWrapper.Dat
                    var datProperty = skillType.GetProperty("Dat", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                    if (datProperty != null)
                    {
                        var datObject = datProperty.GetValue(skillInfo, null);
                        if (datObject != null)
                        {
                            var datType = datObject.GetType();
                            
                            // Try the exact property names from AC system
                            string[] iconPropertyNames = { "IconID", "Icon", "IconId", "uiGraphic", "GraphicID" };
                            
                            foreach (var propName in iconPropertyNames)
                            {
                                var iconProperty = datType.GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                                if (iconProperty != null)
                                {
                                    var iconValue = iconProperty.GetValue(datObject, null);
                                    if (iconValue != null)
                                    {
                                        if (iconValue is int iconId && iconId > 0)
                                        {
                                            return iconId + 0x6000000;
                                        }
                                        else if (iconValue is uint uiconId && uiconId > 0)
                                        {
                                            return (int)uiconId + 0x6000000;
                                        }
                                    }
                                }
                                else
                                {
                                    // Try as field
                                    var iconField = datType.GetField(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                                    if (iconField != null)
                                    {
                                        var iconValue = iconField.GetValue(datObject);
                                        if (iconValue != null)
                                        {
                                            if (iconValue is int iconId && iconId > 0)
                                            {
                                                return iconId + 0x6000000;
                                            }
                                            else if (iconValue is uint uiconId && uiconId > 0)
                                            {
                                                return (int)uiconId + 0x6000000;
                                            }
                                        }
                                    }
                                }
                            }
                            
                            foreach (var prop in datType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
                            {
                                try
                                {
                                    var val = prop.GetValue(datObject, null);
                                    PluginCore.WriteToChat($"  {prop.Name}: {val} ({prop.PropertyType.Name})");
                                }
                                catch (Exception ex)
                                {
                                    PluginCore.WriteToChat($"  {prop.Name}: <error: {ex.Message}> ({prop.PropertyType.Name})");
                                }
                            }
                        }
                        else
                        {
                        }
                    }
                    else
                    {
                    }
                    
                    // Method 3: Try direct properties on SkillInfoWrapper
                    string[] directPropertyNames = { "IconID", "Icon", "IconId", "GraphicID" };
                    foreach (var propName in directPropertyNames)
                    {
                        var iconProperty = skillType.GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                        if (iconProperty != null)
                        {
                            var iconValue = iconProperty.GetValue(skillInfo, null);
                            if (iconValue is int iconId && iconId > 0)
                            {
                                return iconId + 0x6000000;
                            }
                        }
                    }
                }
                catch
                {
                }
                
                // Fallback to predefined mapping
                return GetFallbackSkillIcon(skillId);
            }
            catch
            {
                return GetFallbackSkillIcon(skillId);
            }
        }
        
        private string GetSkillName(int skillId)
        {
            var skillNames = new Dictionary<int, string>
            {
                [1] = "Axe", [2] = "Bow", [3] = "Crossbow", [4] = "Dagger", [5] = "Mace",
                [6] = "Melee Defense", [7] = "Missile Defense", [8] = "Sling", [9] = "Spear", [10] = "Staff",
                [11] = "Sword", [12] = "Thrown Weapons", [13] = "Unarmed Combat", [14] = "Arcane Lore", [15] = "Magic Defense",
                [16] = "Mana Conversion", [17] = "Spellcraft", [18] = "Item Tinkering", [19] = "Assess Person", [20] = "Deception",
                [21] = "Healing", [22] = "Jump", [23] = "Lockpick", [24] = "Run", [25] = "Awareness",
                [26] = "Arms and Armor Repair", [27] = "Assess Creature", [28] = "Weapon Tinkering", [29] = "Armor Tinkering", [30] = "Magic Item Tinkering",
                [31] = "Creature Enchantment", [32] = "Item Enchantment", [33] = "Life Magic", [34] = "War Magic", [35] = "Leadership",
                [36] = "Loyalty", [37] = "Fletching", [38] = "Alchemy", [39] = "Cooking", [40] = "Salvaging",
                [41] = "Two Handed Combat", [42] = "Gearcraft", [43] = "Void Magic", [44] = "Heavy Weapons", [45] = "Light Weapons",
                [46] = "Finesse Weapons", [47] = "Missile Weapons", [48] = "Shield", [49] = "Dual Wield", [50] = "Recklessness",
                [51] = "Sneak Attack", [52] = "Dirty Fighting", [53] = "Threat Assessment", [54] = "Summoning"
            };
            
            return skillNames.ContainsKey(skillId) ? skillNames[skillId] : $"Unknown({skillId})";
        }
        
        private int GetRealSkillIconFromDat(int skillId)
        {
            try
            {
                // Try using FileService SkillTable directly (similar to CharacterCreation.cs pattern)
                var fileService = CoreManager.Current.Filter<Decal.Filters.FileService>();
                if (fileService?.SkillTable != null)
                {
                    // Try to get skill data from the skill table
                    try
                    {
                        // Access SkillTable via reflection to get skill data
                        var skillTableType = fileService.SkillTable.GetType();
                        
                        // Look for methods that can get skill by ID
                        var methods = skillTableType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                        foreach (var method in methods)
                        {
                            if (method.Name.Contains("Get") || method.Name.Contains("get") || method.Name == "Item")
                            {
                                var parameters = method.GetParameters();
                                if (parameters.Length == 1 && (parameters[0].ParameterType == typeof(int) || parameters[0].ParameterType == typeof(uint)))
                                {
                                    try
                                    {
                                        var skillData = method.Invoke(fileService.SkillTable, new object[] { skillId });
                                        if (skillData != null)
                                        {
                                            
                                            // Look for icon properties on the skill data
                                            var skillDataType = skillData.GetType();
                                            string[] iconProps = { "IconID", "Icon", "IconId", "GraphicID", "uiGraphic" };
                                            
                                            foreach (var propName in iconProps)
                                            {
                                                var iconProp = skillDataType.GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                                                if (iconProp != null)
                                                {
                                                    var iconValue = iconProp.GetValue(skillData, null);
                                                    if (iconValue is int iconInt && iconInt > 0)
                                                    {
                                                        return iconInt;
                                                    }
                                                    else if (iconValue is uint iconUint && iconUint > 0)
                                                    {
                                                        return (int)iconUint;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    catch
                                    {
                                        // Method call failed, try next one
                                    }
                                }
                            }
                        }
                    }
                    catch
                    {
                    }
                }
                else
                {
                }
                
                return 0; // No icon found
            }
            catch
            {
                return 0;
            }
        }
        
        private int? GetFallbackSkillIcon(int skillId)
        {
            // Use proven working icon IDs from the recall spells system
            // These icons are confirmed to display correctly in VVS
            var skillIconMap = new Dictionary<int, int>
            {
                // Magic Skills - Use magical/mystical icons (from recalls system)
                [14] = 0x6002D14, // Arcane Lore - Portal icon (default recall icon)
                [16] = 0x60011F9, // Mana Conversion - Green circle (confirmed working)
                [31] = 0x6002D14, // Creature Enchantment - Portal icon
                [32] = 0x6002D14, // Item Enchantment - Portal icon  
                [33] = 0x60011F9, // Life Magic - Green circle (life/healing)
                [34] = 0x60011F8, // War Magic - Red circle (destruction)
                [43] = 0x600287A, // Void Magic - Gray dot (void)
                [54] = 0x6002D14, // Summoning - Portal icon
                
                // Combat Skills - Use distinct working icons
                [41] = 0x60011F8, // Two Handed Combat - Red circle
                [44] = 0x60011F8, // Heavy Weapons - Red circle
                [45] = 0x60028FC, // Light Weapons - Up arrow (from recalls)
                [46] = 0x60028FD, // Finesse Weapons - Down arrow (from recalls)
                [47] = 0x60020B5, // Missile Weapons - Question mark (from recalls)
                [48] = 0x600287A, // Shield - Gray dot
                [49] = 0x60011F8, // Dual Wield - Red circle
                [50] = 0x60011F8, // Recklessness - Red circle
                [51] = 0x600287A, // Sneak Attack - Gray dot
                [52] = 0x60011F8, // Dirty Fighting - Red circle
                
                // Defense Skills - Use defensive icons
                [6] = 0x600287A,  // Melee Defense - Gray dot
                [7] = 0x600287A,  // Missile Defense - Gray dot  
                [15] = 0x600287A, // Magic Defense - Gray dot
                
                // Misc Skills - Use varied working icons
                [19] = 0x60020B5, // Assess Person - Question mark (from recalls)
                [20] = 0x60020B5, // Deception - Question mark
                [21] = 0x60011F9, // Healing - Green circle
                [22] = 0x60028FC, // Jump - Up arrow (motion)
                [23] = 0x60020B5, // Lockpick - Question mark
                [24] = 0x60028FC, // Run - Up arrow (motion)
                [27] = 0x60020B5, // Assess Creature - Question mark
                [35] = 0x60020B5, // Leadership - Question mark
                [36] = 0x60020B5, // Loyalty - Question mark
                
                // Craft Skills - Use working craft icons
                [18] = 0x600287A, // Item Tinkering - Gray dot
                [28] = 0x600287A, // Weapon Tinkering - Gray dot
                [29] = 0x600287A, // Armor Tinkering - Gray dot
                [30] = 0x600287A, // Magic Item Tinkering - Gray dot
                [37] = 0x600287A, // Fletching - Gray dot
                [38] = 0x600287A, // Alchemy - Gray dot
                [39] = 0x600287A, // Cooking - Gray dot
                [40] = 0x600287A, // Salvaging - Gray dot
                
                // Retired weapon skills - Use weapon-style icons
                [1] = 0x60011F8,  // Axe - Red circle
                [2] = 0x60028FC,  // Bow - Up arrow (projectile)
                [3] = 0x60028FC,  // Crossbow - Up arrow (projectile)
                [4] = 0x60011F8,  // Dagger - Red circle
                [5] = 0x60011F8,  // Mace - Red circle
                [8] = 0x60028FC,  // Sling - Up arrow (projectile)
                [9] = 0x60011F8,  // Spear - Red circle
                [10] = 0x60011F8, // Staff - Red circle
                [11] = 0x60011F8, // Sword - Red circle
                [12] = 0x60028FC, // Thrown Weapons - Up arrow (projectile)
                [13] = 0x60011F8  // Unarmed Combat - Red circle
            };
            
            if (skillIconMap.ContainsKey(skillId))
            {
                return skillIconMap[skillId];
            }
            
            // Final fallback to proven working icon from recalls system
            return 0x6002D14; // Portal icon - confirmed working in recalls
        }
        
        private int ComputeCantripIcon(CantripInfo cantrip)
        {
            try
            {
                // Green circle for active cantrips, red circle for missing cantrips
                if (cantrip.Value != "N/A")
                {
                    return 0x60011F9; // Green circle - has cantrip
                }
                else
                {
                    return 0x60011F8; // Red circle - missing cantrip
                }
            }
            catch
            {
                return 0x60011F8; // Red circle on error
            }
        }
        
        private void DetectCantrip(int spellId)
        {
            try
            {
                // Get spell name from SpellManager
                string spellName = GetSpellName(spellId);
                if (string.IsNullOrEmpty(spellName)) 
                {
                    return;
                }
                
                // Debug output to see what spells we're processing
                
                // Define cantrip levels and their patterns
                var cantripPatterns = new Dictionary<string, (string level, System.Drawing.Color color)>
                {
                    ["Minor"] = ("Minor", System.Drawing.Color.White),
                    ["Moderate"] = ("Moderate", System.Drawing.Color.Green),
                    ["Major"] = ("Major", System.Drawing.Color.Blue),
                    ["Epic"] = ("Epic", System.Drawing.Color.Purple),
                    ["Legendary"] = ("Legendary", System.Drawing.Color.Orange)
                };
                
                // Check each cantrip level
                foreach (var cantripPattern in cantripPatterns)
                {
                    string pattern = cantripPattern.Key;
                    var (level, color) = cantripPattern.Value;
                    
                    if (!spellName.StartsWith(pattern + " ")) continue;
                    
                    // Remove the level prefix to get the skill/attribute name
                    string skillPart = spellName.Substring(pattern.Length + 1);
                    
                    // Get the spell icon for this cantrip spell
                    int spellIconId = GetRealSpellIcon(spellId);
                    if (spellIconId == 0)
                    {
                        spellIconId = 0x6002D14; // Default fallback icon
                    }
                    else
                    {
                    }
                    
                    // Try to match Protection Auras first (exact format: "Minor Armor", "Epic Bludgeoning Ward")
                    if (MatchProtectionAura(skillPart, level, color, spellIconId)) 
                    {
                        return;
                    }
                    
                    // Try to match Attributes (exact format: "Minor Strength", "Epic Focus")
                    if (MatchAttribute(skillPart, level, color, spellIconId)) 
                    {
                        return;
                    }
                    
                    // Try to match Skills using the replacement mappings
                    if (MatchSkill(skillPart, level, color, spellIconId)) 
                    {
                        return;
                    }
                    
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error detecting cantrip for spell {spellId}: {ex.Message}");
            }
        }
        
        private bool MatchProtectionAura(string skillPart, string level, System.Drawing.Color color, int spellIconId)
        {
            // Map AC cantrip spell names to protection aura names
            var protectionMappings = new Dictionary<string, string>
            {
                ["Armor"] = "Armor",
                ["Bludgeoning Ward"] = "Bludgeoning Ward",
                ["Piercing Ward"] = "Piercing Ward", 
                ["Slashing Ward"] = "Slashing Ward",
                ["Flame Ward"] = "Flame Ward",
                ["Frost Ward"] = "Frost Ward",
                ["Cold Ward"] = "Frost Ward",        // AC also uses "Cold Ward"
                ["Acid Ward"] = "Acid Ward",
                ["Storm Ward"] = "Storm Ward",       // AC spell is "Storm Ward"
                ["Lightning Ward"] = "Storm Ward",   // AC also uses "Lightning Ward"
                
                // Add more variations that might appear in AC spell names
                ["Bludgeoning Protection"] = "Bludgeoning Ward",
                ["Piercing Protection"] = "Piercing Ward",
                ["Slashing Protection"] = "Slashing Ward", 
                ["Fire Protection"] = "Flame Ward",
                ["Cold Protection"] = "Frost Ward",
                ["Acid Protection"] = "Acid Ward",
                ["Lightning Protection"] = "Storm Ward",
                
                // Single word variations
                ["Bludgeoning"] = "Bludgeoning Ward",
                ["Piercing"] = "Piercing Ward",
                ["Slashing"] = "Slashing Ward",
                ["Fire"] = "Flame Ward",
                ["Flame"] = "Flame Ward", 
                ["Cold"] = "Frost Ward",
                ["Frost"] = "Frost Ward",
                ["Acid"] = "Acid Ward",
                ["Lightning"] = "Storm Ward",
                ["Storm"] = "Storm Ward"
            };
            
            foreach (var mapping in protectionMappings)
            {
                if (skillPart.Equals(mapping.Key, StringComparison.OrdinalIgnoreCase))
                {
                    // Create the cantrip entry if it doesn't exist
                    if (!Cantrips["Protection Auras"].ContainsKey(mapping.Value))
                    {
                        Cantrips["Protection Auras"][mapping.Value] = new CantripInfo 
                        { 
                            Name = mapping.Value, 
                            Value = "N/A", 
                            Color = System.Drawing.Color.White 
                        };
                    }
                    
                    var cantrip = Cantrips["Protection Auras"][mapping.Value];
                    if (cantrip.Value == "N/A" || IsHigherCantripLevel(level, cantrip.Value))
                    {
                        cantrip.Value = level;
                        cantrip.Color = color;
                        cantrip.SpellIconId = spellIconId; // Use the actual spell icon from the cantrip
                    }
                    return true;
                }
            }
            return false;
        }
        
        private bool MatchAttribute(string skillPart, string level, System.Drawing.Color color, int spellIconId)
        {
            // Clean the skill part - remove extra spaces and normalize
            string cleanedSkillPart = skillPart.Trim();
            
            var attributeMappings = new Dictionary<string, string>
            {
                ["Strength"] = "Strength",
                ["Endurance"] = "Endurance", 
                ["Coordination"] = "Coordination",
                ["Quickness"] = "Quickness",
                ["Focus"] = "Focus",
                ["Self"] = "Willpower",      // "Minor Self" -> Willpower
                ["Willpower"] = "Willpower"  // "Epic Willpower" -> Willpower
            };
            
            
            foreach (var mapping in attributeMappings)
            {
                if (cleanedSkillPart.Equals(mapping.Key, StringComparison.OrdinalIgnoreCase))
                {
                    
                    // Create the cantrip entry if it doesn't exist
                    if (!Cantrips["Attributes"].ContainsKey(mapping.Value))
                    {
                        Cantrips["Attributes"][mapping.Value] = new CantripInfo 
                        { 
                            Name = mapping.Value, 
                            Value = "N/A", 
                            Color = System.Drawing.Color.White 
                        };
                    }
                    
                    var cantrip = Cantrips["Attributes"][mapping.Value];
                    if (cantrip.Value == "N/A" || IsHigherCantripLevel(level, cantrip.Value))
                    {
                        cantrip.Value = level;
                        cantrip.Color = color;
                        cantrip.SpellIconId = spellIconId; // Use the actual spell icon from the cantrip
                    }
                    return true;
                }
            }
            
            // Try more flexible matching - check if the cleaned skill part contains any of our attributes
            foreach (var mapping in attributeMappings)
            {
                if (cleanedSkillPart.IndexOf(mapping.Key, StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    
                    // Create the cantrip entry if it doesn't exist
                    if (!Cantrips["Attributes"].ContainsKey(mapping.Value))
                    {
                        Cantrips["Attributes"][mapping.Value] = new CantripInfo 
                        { 
                            Name = mapping.Value, 
                            Value = "N/A", 
                            Color = System.Drawing.Color.White 
                        };
                    }
                    
                    var cantrip = Cantrips["Attributes"][mapping.Value];
                    if (cantrip.Value == "N/A" || IsHigherCantripLevel(level, cantrip.Value))
                    {
                        cantrip.Value = level;
                        cantrip.Color = color;
                        cantrip.SpellIconId = spellIconId; // Use the actual spell icon from the cantrip
                    }
                    return true;
                }
            }
            
            return false;
        }
        
        private bool MatchSkill(string skillPart, string level, System.Drawing.Color color, int spellIconId)
        {
            // Map actual cantrip spell names to our skill names
            var skillMappings = new Dictionary<string, string>
            {
                // Defense skills (with AC spell name mappings)
                ["Magic Resistance"] = "MagicResistance",
                ["Invulnerability"] = "Invulnerability", 
                ["Impregnability"] = "Impgrenability",   // Note: AC uses "Impregnability" not "Impgrenability"
                
                // Weapon skills (with AC spell name patterns)
                ["Heavy Weapon Aptitude"] = "HeavyWeapon",
                ["Light Weapon Aptitude"] = "LightWeapon", 
                ["Finesse Weapon Aptitude"] = "FinesseWeapon",
                ["Missile Weapon Aptitude"] = "MissileWeapon",
                
                // Craft skills (with AC spell name patterns)
                ["Alchemical Prowess"] = "Alchemy",
                ["Arcane Prowess"] = "Arcane Lore",
                ["Armor Tinkering Expertise"] = "Armor Tinkering",
                ["Assess Creature"] = "Assess Creature",
                ["Assess Person"] = "Assess Person", 
                ["Cooking Prowess"] = "Cooking",
                ["Deception Prowess"] = "Deception",
                ["Fletching Prowess"] = "Fletching",
                ["Healing Prowess"] = "Healing",
                ["Item Tinkering Expertise"] = "Item Tinkering",
                ["Leadership"] = "Leadership",
                ["Lockpick Prowess"] = "Lockpick",
                ["Fealty"] = "Loyalty",  // AC uses "Fealty" for Loyalty
                ["Magic Item Tinkering Expertise"] = "Magic Item Tinkering",
                ["Mana Conversion Prowess"] = "Mana Conversion",
                ["Jumping Prowess"] = "Jump",   // AC has Jump cantrips
                ["Salvaging Aptitude"] = "Salvaging",
                ["Weapon Tinkering Expertise"] = "Weapon Tinkering",
                
                // Magic schools (with AC spell name patterns)
                ["War Magic Aptitude"] = "War Magic",
                ["Life Magic Aptitude"] = "Life Magic", 
                ["Creature Enchantment Aptitude"] = "Creature Enchantment",
                ["Item Enchantment Aptitude"] = "Item Enchantment",
                ["Void Magic Aptitude"] = "Void Magic",
                ["Summoning Prowess"] = "Summoning",
                
                // Combat skills
                ["Two Handed Combat Aptitude"] = "Two Handed Combat",
                ["Dual Wield Aptitude"] = "Dual Wield",
                ["Shield Aptitude"] = "Shield",
                ["Sneak Attack Prowess"] = "Sneak Attack",
                ["Dirty Fighting Prowess"] = "Dirty Fighting",
                ["Recklessness"] = "Recklessness"
            };
            
            foreach (var mapping in skillMappings)
            {
                if (skillPart.Equals(mapping.Key, StringComparison.OrdinalIgnoreCase))
                {
                    // Check both specialized and trained skills
                    foreach (var category in new[] { "Specialized Skills", "Trained Skills" })
                    {
                        if (Cantrips[category].ContainsKey(mapping.Value))
                        {
                            var cantrip = Cantrips[category][mapping.Value];
                            if (cantrip.Value == "N/A" || IsHigherCantripLevel(level, cantrip.Value))
                            {
                                cantrip.Value = level;
                                cantrip.Color = color;
                                cantrip.SpellIconId = spellIconId; // Use the actual spell icon instead of skill icon
                                cantrip.IconId = null; // Clear any skill icon reference
                            }
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        
        private string GetSpellName(int spellId)
        {
            try
            {
                // Use our existing SpellManager that was already working
                var spell = SpellManager.GetSpell(spellId);
                if (spell != null)
                {
                    return spell.Name;
                }
                return "";
            }
            catch
            {
                return "";
            }
        }
        
        private bool IsHigherCantripLevel(string newLevel, string currentLevel)
        {
            var levels = new Dictionary<string, int>
            {
                ["Minor"] = 1,
                ["Moderate"] = 2,
                ["Major"] = 3,
                ["Epic"] = 4,
                ["Legendary"] = 5
            };
            
            if (!levels.ContainsKey(newLevel) || !levels.ContainsKey(currentLevel))
                return false;
                
            return levels[newLevel] > levels[currentLevel];
        }
        
        private void TestCantripDetection()
        {
            try
            {
                // Test real AC cantrip spell names to verify the detection logic
                var testSpells = new[]
                {
                    "Major Strength",                    // Attribute cantrip
                    "Epic Coordination",                 // Attribute cantrip
                    "Legendary Focus",                   // Attribute cantrip
                    "Major Willpower",                   // Willpower attribute
                    "Major Invulnerability",             // Melee Defense skill
                    "Major Impregnability",              // Missile Defense skill  
                    "Major Alchemical Prowess",          // Alchemy skill
                    "Major Arcane Prowess",              // Arcane Lore skill
                    "Epic Life Magic Aptitude",          // Life Magic skill
                    "Major Fealty",                      // Loyalty skill
                    "Major Armor",                       // Protection aura
                    "Epic Flame Ward",                   // Protection aura
                    "Legendary Storm Ward"               // Protection aura
                };
                
                foreach (var spellName in testSpells)
                {
                    TestDetectCantripByName(spellName);
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error in test cantrip detection: {ex.Message}");
            }
        }
        
        private void TestDetectCantripByName(string spellName)
        {
            try
            {
                // Simulate the detection logic with a fake spell name
                
                // Define cantrip levels and their patterns
                var cantripPatterns = new Dictionary<string, (string level, System.Drawing.Color color)>
                {
                    ["Minor"] = ("Minor", System.Drawing.Color.White),
                    ["Moderate"] = ("Moderate", System.Drawing.Color.Green),
                    ["Major"] = ("Major", System.Drawing.Color.Blue),
                    ["Epic"] = ("Epic", System.Drawing.Color.Purple),
                    ["Legendary"] = ("Legendary", System.Drawing.Color.Orange)
                };
                
                // Check each cantrip level
                foreach (var cantripPattern in cantripPatterns)
                {
                    string pattern = cantripPattern.Key;
                    var (level, color) = cantripPattern.Value;
                    
                    if (!spellName.StartsWith(pattern + " ")) continue;
                    
                    // Remove the level prefix to get the skill/attribute name
                    string skillPart = spellName.Substring(pattern.Length + 1);
                    
                    
                    // Get a test spell icon (use default for testing)
                    int testSpellIconId = 0x6002D14;
                    
                    // Try to match Protection Auras first
                    if (MatchProtectionAura(skillPart, level, color, testSpellIconId)) 
                    {
                        return;
                    }
                    
                    // Try to match Attributes
                    if (MatchAttribute(skillPart, level, color, testSpellIconId)) 
                    {
                        return;
                    }
                    
                    // Try to match Skills
                    if (MatchSkill(skillPart, level, color, testSpellIconId)) 
                    {
                        return;
                    }
                    
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error testing cantrip detection: {ex.Message}");
            }
        }

        #region Weapon Data Structures
        public class TrackedWeaponInfo
        {
            public string Name { get; set; }
            public string Category { get; set; }
            public string WeaponType { get; set; }
            public string Status { get; set; }
            public bool IsAcquired { get; set; }
            public int ItemId { get; set; }
            public int IconId { get; set; }
        }

        public Dictionary<string, List<TrackedWeaponInfo>> WeaponCategories { get; private set; }
        #endregion

        public void RefreshWeapons()
        {
            try
            {
                if (CoreManager.Current?.CharacterFilter?.Name == null) return;
                
                InitializeNewWeaponData();
                CheckAcquiredWeapons();
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error refreshing weapons: {ex.Message}");
            }
        }

        private void InitializeNewWeaponData()
        {
            WeaponCategories = new Dictionary<string, List<TrackedWeaponInfo>>
            {
                ["Legendary Weapons"] = new List<TrackedWeaponInfo>
                {
                    new TrackedWeaponInfo { Name = "Bow of the Quiddity", Category = "Legendary Weapons", WeaponType = "Bow", ItemId = 23044, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Sword of the Quiddity", Category = "Legendary Weapons", WeaponType = "Sword", ItemId = 23039, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Mace of the Quiddity", Category = "Legendary Weapons", WeaponType = "Mace", ItemId = 23040, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Atlatl of the Quiddity", Category = "Legendary Weapons", WeaponType = "Atlatl", ItemId = 23043, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Staff of the Quiddity", Category = "Legendary Weapons", WeaponType = "Staff", ItemId = 23041, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Dagger of the Quiddity", Category = "Legendary Weapons", WeaponType = "Dagger", ItemId = 23042, Status = "Unknown" }
                },
                ["Slayer Weapons"] = new List<TrackedWeaponInfo>
                {
                    new TrackedWeaponInfo { Name = "Shadowfire Isparian Bow", Category = "Slayer Weapons", WeaponType = "Bow", ItemId = 20636, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Shadowfire Isparian Sword", Category = "Slayer Weapons", WeaponType = "Sword", ItemId = 20631, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Shadowfire Isparian Staff", Category = "Slayer Weapons", WeaponType = "Staff", ItemId = 20633, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Shadowfire Isparian Dagger", Category = "Slayer Weapons", WeaponType = "Dagger", ItemId = 20634, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Shadowfire Isparian Axe", Category = "Slayer Weapons", WeaponType = "Axe", ItemId = 20635, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Shadowfire Isparian Mace", Category = "Slayer Weapons", WeaponType = "Mace", ItemId = 20632, Status = "Unknown" }
                },
                ["Society Weapons"] = new List<TrackedWeaponInfo>
                {
                    new TrackedWeaponInfo { Name = "Radiant Blood Sword", Category = "Society Weapons", WeaponType = "Sword", ItemId = 32834, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Celestial Hand Sword", Category = "Society Weapons", WeaponType = "Sword", ItemId = 32835, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Eldritch Web Sword", Category = "Society Weapons", WeaponType = "Sword", ItemId = 32836, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Radiant Blood Bow", Category = "Society Weapons", WeaponType = "Bow", ItemId = 32837, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Celestial Hand Bow", Category = "Society Weapons", WeaponType = "Bow", ItemId = 32838, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Eldritch Web Bow", Category = "Society Weapons", WeaponType = "Bow", ItemId = 32839, Status = "Unknown" }
                },
                ["Atlan Weapons"] = new List<TrackedWeaponInfo>
                {
                    new TrackedWeaponInfo { Name = "Atlan Sword", Category = "Atlan Weapons", WeaponType = "Sword", ItemId = 11648, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Atlan Axe", Category = "Atlan Weapons", WeaponType = "Axe", ItemId = 11649, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Atlan Mace", Category = "Atlan Weapons", WeaponType = "Mace", ItemId = 11650, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Atlan Spear", Category = "Atlan Weapons", WeaponType = "Spear", ItemId = 11651, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Atlan Staff", Category = "Atlan Weapons", WeaponType = "Staff", ItemId = 11652, Status = "Unknown" },
                    new TrackedWeaponInfo { Name = "Atlan Dagger", Category = "Atlan Weapons", WeaponType = "Dagger", ItemId = 11653, Status = "Unknown" }
                }
            };
        }

        private void CheckAcquiredWeapons()
        {
            try
            {
                // Get inventory items
                var worldFilter = CoreManager.Current.WorldFilter;
                var inventoryItems = worldFilter.GetInventory().Cast<WorldObject>().ToList();
                
                // Check each weapon category
                foreach (var category in WeaponCategories)
                {
                    foreach (var weapon in category.Value)
                    {
                        // Check if weapon is acquired by name matching
                        var foundItem = inventoryItems.FirstOrDefault(item => 
                            item.Name.Contains(weapon.Name) || 
                            weapon.Name.Contains(item.Name));
                        
                        if (foundItem != null)
                        {
                            weapon.IsAcquired = true;
                            weapon.Status = "Acquired";
                            weapon.IconId = foundItem.Icon + 0x6000000;
                        }
                        else
                        {
                            weapon.IsAcquired = false;
                            weapon.Status = "Not Acquired";
                            weapon.IconId = 0x6002D14; // Default icon
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                PluginCore.WriteToChat($"Error checking acquired weapons: {ex.Message}");
            }
        }
        #endregion

        #region Cleanup
        public void Dispose()
        {
            // Cleanup if needed
        }
        #endregion
    }
}
