using Godot;
using Godot.Collections;
using Mr.BrickAdventures.Autoloads;
using Mr.BrickAdventures.scripts.interfaces;
using Mr.BrickAdventures.scripts.Resources;

namespace Mr.BrickAdventures.scripts.components;

[GlobalClass]
public partial class SkillUnlockerComponent : Node
{
    public SkillManager SkillManager { get; private set; }

    [Signal]
    public delegate void SkillUnlockedEventHandler(SkillData skill);

    private GameStateStore Store => GameStateStore.Instance;

    public override void _Ready()
    {
        SkillManager = SkillManager.Instance;
    }

    private bool HasEnoughCoins(int amount) => (Store?.GetTotalCoins() ?? 0) >= amount;

    public bool TryUnlockSkill(SkillData skill)
    {
        if (Store == null) return false;
        if (Store.IsSkillUnlocked(skill)) return false;
        if (!HasEnoughCoins(skill.Upgrades[0].Cost)) return false;

        skill.Level = 1;
        Store.RemoveCoins(skill.Upgrades[0].Cost);
        Store.UnlockSkillInSession(skill);
        SkillManager.AddSkill(skill);
        EmitSignalSkillUnlocked(skill);

        return true;
    }

    public void UnlockAllSkills()
    {
        var availableSkills = SkillManager.AvailableSkills;

        foreach (var skill in availableSkills)
        {
            Store?.UnlockSkillPermanently(skill);
            EmitSignalSkillUnlocked(skill);
        }

        SkillManager.ApplyUnlockedSkills();
    }

    public bool TryUpgradeSkill(SkillData skill)
    {
        if (Store == null) return false;
        if (!Store.IsSkillUnlocked(skill)) return false;
        if (skill.Level >= skill.MaxLevel) return false;
        if (!HasEnoughCoins(skill.Upgrades[skill.Level].Cost)) return false;

        Store.RemoveCoins(skill.Upgrades[skill.Level].Cost);
        skill.Level++;
        if (SkillManager.ActiveComponents.TryGetValue(skill.Name, out Variant componentVariant))
        {
            var component = componentVariant.AsGodotObject();
            if (component is ISkill skillInstance)
                skillInstance.ApplyUpgrade(skill.Upgrades[skill.Level - 1]);
        }
        EmitSignalSkillUnlocked(skill);
        return true;
    }
}
