using Theriapolis.Core.Rules.Stats;

namespace Theriapolis.Game.UI;

/// <summary>
/// Author-curated UI text that the wizard surfaces but isn't worth pushing
/// into JSON — skill descriptions, language metadata, ability labels, and
/// the informational class↔clade recommendation table.
///
/// Sourced from the Phase 5 character-creator design handoff
/// (`_design_handoff/character_creation/` snapshot, src/data.jsx). Keeping
/// these here rather than in <c>Content/Data/</c> lets the design tone live
/// next to the code that consumes it.
/// </summary>
public static class CodexCopy
{
    /// <summary>STR/DEX/CON/INT/WIS/CHA → long display name.</summary>
    public static readonly System.Collections.Generic.IReadOnlyDictionary<AbilityId, string> AbilityLabels =
        new System.Collections.Generic.Dictionary<AbilityId, string>
        {
            [AbilityId.STR] = "Strength",
            [AbilityId.DEX] = "Dexterity",
            [AbilityId.CON] = "Constitution",
            [AbilityId.INT] = "Intellect",
            [AbilityId.WIS] = "Wisdom",
            [AbilityId.CHA] = "Charisma",
        };

    /// <summary>SizeCategory snake_case → pretty label.</summary>
    public static string SizeLabel(string sizeKey) => sizeKey switch
    {
        "small"        => "Small",
        "medium"       => "Medium",
        "medium_large" => "Medium-Large",
        "large"        => "Large",
        _              => sizeKey,
    };

    /// <summary>Skill id (snake_case) → display name.</summary>
    public static string SkillName(string skillId) => skillId switch
    {
        "acrobatics"      => "Acrobatics",
        "animal_handling" => "Animal Handling",
        "arcana"          => "Arcana",
        "athletics"       => "Athletics",
        "deception"       => "Deception",
        "history"         => "History",
        "insight"         => "Insight",
        "intimidation"    => "Intimidation",
        "investigation"   => "Investigation",
        "medicine"        => "Medicine",
        "nature"          => "Nature",
        "perception"      => "Perception",
        "performance"     => "Performance",
        "persuasion"      => "Persuasion",
        "religion"        => "Religion",
        "sleight_of_hand" => "Sleight of Hand",
        "stealth"         => "Stealth",
        "survival"        => "Survival",
        _                 => skillId,
    };

    /// <summary>One-sentence skill description in the codex's tone (from the design's data.jsx).</summary>
    public static string SkillDescription(string skillId) => skillId switch
    {
        "acrobatics"      => "Tumbling, balance, and the kind of footwork that keeps you upright on a coliseum sand-floor or a warren-rope. Body-cunning under pressure.",
        "animal_handling" => "Reading and steering non-sentient beasts — feral hounds, draft-kine, the wild cousins of your own clade.",
        "arcana"          => "Knowledge of the older magics: scent-sorcery, blood-sigil, the half-forgotten rites that pre-date the Covenant of Claws.",
        "athletics"       => "Raw physical effort. Climbing scaffold, swimming the foul canal, hauling a packmate from the pit, breaking a hold.",
        "deception"       => "Speaking convincingly past your scent. The art of the false posture, the planted rumor, the answer that is technically true.",
        "history"         => "The long memory of Theriapolis — the Imperium's fall, the Compact's ratification, which clade owes which other a centuries-old debt.",
        "insight"         => "Reading another's true posture beneath their words. Catching the off-note in a snarl, the held breath, the lie in a friendly tail.",
        "intimidation"    => "Bared-teeth diplomacy. The threat made plain enough that violence is not required to extract compliance.",
        "investigation"   => "Methodical search and inference: scene-reading, document-sifting, the patient accumulation of small facts into a verdict.",
        "medicine"        => "Field surgery, poultice-craft, knowing which clade tolerates which tincture. Stabilizing the dying without finishing them.",
        "nature"          => "Knowledge of the wild outside the city wall — terrain, weather, plant-lore, and the unsigned beasts that observe no Covenant.",
        "perception"      => "Awareness through every sense your clade gives you: ear-cock, scent-prickle, the half-glimpsed shape at the edge of vision.",
        "performance"     => "Holding an audience — coliseum crowd, courtroom gallery, market square. Song, oratory, the body that compels watching.",
        "persuasion"      => "Open-handed argument. The case made on its merits, the appeal to mutual benefit, the patient construction of agreement.",
        "religion"        => "The hymn-cycles of the Cervid liturgy, the Compact's sacred clauses, the small household rites your clade keeps without thinking.",
        "sleight_of_hand" => "Quiet fingers — pickpocketing, palmed coins, the swap performed under another's nose.",
        "stealth"         => "Movement unseen and unsmelled. Wind-checking, scent-suppression, the slow weight-shift on a creaking floor.",
        "survival"        => "Field-craft beyond the wall: tracking, foraging, fire-making, knowing which run-off is safe to drink.",
        _                 => "",
    };

    /// <summary>Skill id → governing ability.</summary>
    public static AbilityId SkillAbility(string skillId)
    {
        try { return SkillIdExtensions.FromJson(skillId).Ability(); }
        catch { return AbilityId.STR; }
    }

    /// <summary>
    /// <see cref="SkillId"/> enum → snake_case JSON id. Inverse of
    /// <see cref="SkillIdExtensions.FromJson"/>. Required because
    /// <c>enum.ToString().ToLowerInvariant()</c> produces "sleightofhand"
    /// for <c>SleightOfHand</c>, which doesn't match the JSON-keyed
    /// dictionaries (skill name / skill description).
    /// </summary>
    public static string SkillIdToJson(SkillId s) => s switch
    {
        SkillId.Acrobatics      => "acrobatics",
        SkillId.AnimalHandling  => "animal_handling",
        SkillId.Arcana          => "arcana",
        SkillId.Athletics       => "athletics",
        SkillId.Deception       => "deception",
        SkillId.History         => "history",
        SkillId.Insight         => "insight",
        SkillId.Intimidation    => "intimidation",
        SkillId.Investigation   => "investigation",
        SkillId.Medicine        => "medicine",
        SkillId.Nature          => "nature",
        SkillId.Perception      => "perception",
        SkillId.Performance     => "performance",
        SkillId.Persuasion      => "persuasion",
        SkillId.Religion        => "religion",
        SkillId.SleightOfHand   => "sleight_of_hand",
        SkillId.Stealth         => "stealth",
        SkillId.Survival        => "survival",
        _                       => s.ToString().ToLowerInvariant(),
    };

    /// <summary>Language id → display name.</summary>
    public static string LanguageName(string langId) => langId switch
    {
        "common"   => "Common",
        "canid"    => "Canid",
        "felid"    => "Felid",
        "mustelid" => "Mustelid",
        "ursid"    => "Ursid",
        "cervid"   => "Cervid",
        "bovid"    => "Bovid",
        "leporid"  => "Leporid",
        _          => langId,
    };

    /// <summary>Language id → flavor description for hover/detail panels.</summary>
    public static string LanguageDescription(string langId) => langId switch
    {
        "common"   => "The market-and-courthouse trade tongue of Theriapolis. Spoken by every clade.",
        "canid"    => "Pack-tongue of the Canidae. Heavy with subsonic registers and scent-words non-Canid speakers cannot fully parse.",
        "felid"    => "Sinuous and tonal, with a parallel tail-and-ear pidgin. Felid speakers trade in implication and pause.",
        "mustelid" => "Quick, percussive trade-speech of the Mustelidae. Famous for its dense vocabulary of musks, debts, and small grievances.",
        "ursid"    => "Slow, low-register growl-speech. Ursid grammar prefers final emphasis — the important word always comes last.",
        "cervid"   => "Old, hymn-shaped tongue of the Cervidae. Most speakers know Cervid as a song-language for funerals, treaties, and the long calendar.",
        "bovid"    => "Patient, formal speech of the herd-clades. The language of guild-councils and oaths.",
        "leporid"  => "Rapid, twitch-paced chatter of the Leporidae. Uses tense markers for danger and runs faster than most non-Leporidae can follow.",
        _          => "",
    };

    /// <summary>Item id → pretty display name (mirrors items.json's <c>name</c> for the subset used by starting kits).</summary>
    public static string ItemName(string itemId) => itemId switch
    {
        "rend_sword"           => "Rend-sword",
        "chain_shirt"          => "Chain Shirt",
        "buckler"              => "Buckler",
        "healers_kit"          => "Healer's Kit",
        "rations_predator"     => "Rations (predator)",
        "rations_prey"         => "Rations (prey)",
        "hoof_club"            => "Hoof Club",
        "chain_mail"           => "Chain Mail",
        "standard_shield"      => "Standard Shield",
        "paw_axe"              => "Paw-axe",
        "hide_vest"            => "Hide Vest",
        "thorn_blade"          => "Thorn-blade",
        "studded_leather"      => "Studded Leather",
        "claw_bow"             => "Claw-bow",
        "poultice_universal"   => "Universal Poultice",
        "scent_mask_basic"     => "Basic Scent-mask",
        "fang_knife"           => "Fang-knife",
        "leather_harness"      => "Leather Harness",
        "pheromone_vial_calm"  => "Pheromone Vial (calm)",
        "pheromone_vial_fear"  => "Pheromone Vial (fear)",
        "rope_claw_braid"      => "Claw-braid Rope",
        _                       => itemId,
    };

    /// <summary>
    /// Class id → list of clade ids that suit it. Drives the "★ Suits Clade"
    /// recommendation badge on the calling step. Informational only — the
    /// player can still pick any class with any clade.
    /// </summary>
    public static readonly System.Collections.Generic.IReadOnlyDictionary<string, string[]> ClassCladeRecommendations =
        new System.Collections.Generic.Dictionary<string, string[]>
        {
            ["fangsworn"]       = new[] { "canidae", "felidae", "ursidae" },
            ["bulwark"]         = new[] { "bovidae", "ursidae" },
            ["feral"]           = new[] { "ursidae", "mustelidae", "bovidae" },
            ["shadow_pelt"]     = new[] { "felidae", "mustelidae", "leporidae" },
            ["scent_broker"]    = new[] { "canidae", "mustelidae" },
            ["covenant_keeper"] = new[] { "canidae", "bovidae", "cervidae" },
            ["muzzle_speaker"]  = new[] { "felidae", "leporidae" },
            ["claw_wright"]     = new[] { "mustelidae", "leporidae" },
        };

    /// <summary>Returns true if <paramref name="cladeId"/> is one of the recommended clades for <paramref name="classId"/>.</summary>
    public static bool IsSuited(string classId, string cladeId)
    {
        if (!ClassCladeRecommendations.TryGetValue(classId, out var clades)) return false;
        foreach (var c in clades)
            if (string.Equals(c, cladeId, System.StringComparison.OrdinalIgnoreCase))
                return true;
        return false;
    }

    /// <summary>STR/DEX/.../CHA in canonical order (matches the design's `ABILITIES`).</summary>
    public static readonly AbilityId[] AbilityOrder = new[]
    {
        AbilityId.STR, AbilityId.DEX, AbilityId.CON, AbilityId.INT, AbilityId.WIS, AbilityId.CHA,
    };

    /// <summary>Roman numeral 1..7 for stepper labels ("Folio I of VII").</summary>
    public static string Romanize(int n) => n switch
    {
        1 => "I", 2 => "II", 3 => "III", 4 => "IV",
        5 => "V", 6 => "VI", 7 => "VII", 8 => "VIII",
        _ => n.ToString(),
    };

    /// <summary>"+N" for n &gt;= 0, "-N" otherwise.</summary>
    public static string Signed(int n) => n >= 0 ? $"+{n}" : n.ToString();
}
