using Theriapolis.Core.Rules.Stats;
using Theriapolis.Game.CodexUI.Core;
using Theriapolis.Game.CodexUI.Screens;
using Theriapolis.Game.CodexUI.Widgets;
using Theriapolis.Game.UI;

namespace Theriapolis.Game.CodexUI.Steps;

/// <summary>
/// Step VI — Skills. Two-column grid of <see cref="SkillGroupPanel"/>, one
/// per ability. Each panel lists every skill governed by that ability with
/// its current <see cref="CheckboxState"/>. Background-sealed skills are
/// pre-checked and locked; class-pickable skills are toggleable up to the
/// class's <c>SkillsChoose</c> count.
/// </summary>
public static class StepSkills
{
    public static CodexWidget Build(CodexCharacterCreationScreen s, CodexAtlas atlas, CodexHoverPopover popover)
    {
        var col = new Column { Spacing = 14 };
        col.Add(StepCommon.PageIntro(
            "Folio VI — Of Trained Hands",
            "Choose your Skills",
            $"Your background grants {s.Background?.SkillProficiencies.Length ?? 0} skill(s) automatically (sealed). From your calling's offered list, choose {s.Class?.SkillsChoose ?? 0} more."));

        // Meta line
        var meta = new Row { Spacing = 16, VAlignChildren = VAlign.Middle, Padding = new Thickness(14, 12, 14, 12) };
        meta.Add(new CodexLabel($"{s.ChosenSkills.Count} / {s.Class?.SkillsChoose ?? 0} CHOSEN", CodexFonts.DisplaySmall, CodexColors.Ink));
        meta.Add(new CodexLabel($"+ {s.Background?.SkillProficiencies.Length ?? 0} SEALED BY BACKGROUND",
                                CodexFonts.MonoTagSmall, CodexColors.InkMute));
        col.Add(new CodexPanel(atlas, meta));

        // Skill groups by ability
        var bgLocked = new System.Collections.Generic.HashSet<string>(
            s.Background?.SkillProficiencies ?? System.Array.Empty<string>(),
            System.StringComparer.OrdinalIgnoreCase);
        var classOpts = new System.Collections.Generic.HashSet<string>(
            s.Class?.SkillOptions ?? System.Array.Empty<string>(),
            System.StringComparer.OrdinalIgnoreCase);

        var groupedByAbility = new System.Collections.Generic.Dictionary<AbilityId, System.Collections.Generic.List<string>>();
        foreach (var ab in CodexCopy.AbilityOrder) groupedByAbility[ab] = new();
        foreach (var skillId in CodexCharacterCreationScreen.AllSkillIds())
            groupedByAbility[CodexCopy.SkillAbility(skillId)].Add(skillId);

        var grid = new Grid { Columns = 2 };
        foreach (var ab in CodexCopy.AbilityOrder)
            grid.Add(BuildGroup(s, atlas, popover, ab, groupedByAbility[ab], bgLocked, classOpts));
        col.Add(grid);
        return col;
    }

    private static CodexWidget BuildGroup(CodexCharacterCreationScreen s, CodexAtlas atlas, CodexHoverPopover popover,
                                          AbilityId ab, System.Collections.Generic.List<string> skillIds,
                                          System.Collections.Generic.HashSet<string> bgLocked,
                                          System.Collections.Generic.HashSet<string> classOpts)
    {
        var inner = new Column { Spacing = 4 };
        inner.Add(new CodexLabel(CodexCopy.AbilityLabels[ab].ToUpperInvariant(),
                                 CodexFonts.DisplaySmall, CodexColors.Ink));
        foreach (var skillId in skillIds)
        {
            bool fromBg = bgLocked.Contains(skillId);
            bool fromClass = classOpts.Contains(skillId);
            bool checkedNow;
            try { checkedNow = s.ChosenSkills.Contains(SkillIdExtensions.FromJson(skillId)); }
            catch { checkedNow = false; }

            var state = fromBg ? CheckboxState.LockedFromBg
                       : checkedNow ? CheckboxState.Checked
                       : !fromClass ? CheckboxState.Unavailable
                       : CheckboxState.Default;

            string sourceTag = fromBg ? "BACKGROUND" : (fromClass ? "CLASS" : "—");
            var row = new CodexCheckboxRow(CodexCopy.SkillName(skillId), sourceTag, state, atlas);
            string sid = skillId;
            row.OnClick = () =>
            {
                SkillId enumId;
                try { enumId = SkillIdExtensions.FromJson(sid); } catch { return; }
                if (s.ChosenSkills.Contains(enumId)) s.ChosenSkills.Remove(enumId);
                else if (s.ChosenSkills.Count < (s.Class?.SkillsChoose ?? 0)) s.ChosenSkills.Add(enumId);
                s.InvalidateLayout();
            };
            row.OnHover = () =>
                popover.Show(row.Bounds,
                             CodexCopy.SkillName(sid),
                             CodexCopy.SkillDescription(sid),
                             CodexCopy.SkillAbility(sid).ToString());
            inner.Add(row);
        }
        return new CodexPanel(atlas, inner) { Inset = new Thickness(14, 12, 16, 12) };
    }
}
