using Theriapolis.Core.Data;

namespace Theriapolis.Core.Rules.Character;

/// <summary>
/// Phase 6.5 M4 — runtime state for a hybrid character.
///
/// Hybrids are blended from two parent lineages: a <b>Sire</b> (paternal
/// lineage) and a <b>Dam</b> (maternal lineage), of two different clades.
/// One parent is <see cref="DominantParent"/> — the lineage whose physical
/// expression is more visible; this drives Passing eligibility and which
/// clade the PC presents as for casual scent reads.
///
/// The character's own gender is independent of which parent is sire or
/// dam — a male hybrid PC can have a wolf-folk dam and a coyote-folk
/// sire just as readily as the reverse.
///
/// Per <c>theriapolis-rpg-clades.md</c> HYBRID ORIGIN: blend ability mods
/// (one from each parent clade), traits (2 from dominant + 1 from
/// secondary), and inherit *all* universal hybrid detriments — Scent
/// Dysphoria, Illegible Body Language, Social Stigma, Medical
/// Incompatibility (handled by <see cref="HybridDetriments"/>).
///
/// <see cref="PassingActive"/> is toggle-able mid-game; when set, the PC
/// presents as the dominant lineage's clade. Detection by NPCs (Phase 6.5
/// M5) is per-NPC and permanent once revealed.
/// </summary>
public sealed class HybridState
{
    /// <summary>Sire (paternal-lineage) clade id, e.g. "canidae".</summary>
    public string SireClade   { get; init; } = "";

    /// <summary>Sire (paternal-lineage) species id, e.g. "wolf".</summary>
    public string SireSpecies { get; init; } = "";

    /// <summary>Dam (maternal-lineage) clade id, e.g. "leporidae".</summary>
    public string DamClade    { get; init; } = "";

    /// <summary>Dam (maternal-lineage) species id, e.g. "rabbit".</summary>
    public string DamSpecies  { get; init; } = "";

    /// <summary>
    /// Which parent's expression is dominant. Drives Passing presentation
    /// (the PC scent-reads as this parent's clade) and the trait-split:
    /// 2 Clade traits from the dominant parent, 1 from the secondary.
    /// </summary>
    public ParentLineage DominantParent { get; init; }

    /// <summary>
    /// True when the PC is actively trying to pass as their dominant
    /// parent's clade. Toggles on the character sheet; consulted by
    /// Phase 6.5 M5 passing-detection rolls.
    /// </summary>
    public bool PassingActive { get; set; }

    /// <summary>
    /// Phase 6.5 M5 — currently-active scent mask tier (if any). The mask
    /// suppresses scent-based detection per its tier. Phase 6.5 M5 ships
    /// the static tier flag; Phase 8's clock model adds time-based
    /// expiry alongside daily wear.
    /// </summary>
    public ScentMaskTier ActiveMaskTier { get; set; } = ScentMaskTier.None;

    /// <summary>
    /// NPC ids who have personally detected this PC is hybrid. Permanent
    /// once added — disabling Passing later doesn't undo the discovery
    /// for that specific NPC. Phase 6.5 M5 populates this; M4 reserves it
    /// in the schema so save round-trip works pre- and post-M5.
    /// </summary>
    public HashSet<int> NpcsWhoKnow { get; } = new();

    /// <summary>
    /// Convenience: which clade the PC presents as for casual scent reads
    /// (used by Phase 6.5 M5 passing logic and Phase 7 dialogue gates).
    /// Returns the dominant parent's clade id.
    /// </summary>
    public string PresentingCladeId =>
        DominantParent == ParentLineage.Sire ? SireClade : DamClade;

    /// <summary>
    /// Convenience: which species the PC presents as. Same logic as
    /// <see cref="PresentingCladeId"/>.
    /// </summary>
    public string PresentingSpeciesId =>
        DominantParent == ParentLineage.Sire ? SireSpecies : DamSpecies;
}

/// <summary>
/// Phase 6.5 M4 — which parent in a hybrid PC's lineage is the
/// dominant/secondary expression. Sire = paternal lineage, Dam = maternal
/// lineage; the choice is OOC (no gender semantics for the character
/// themselves, just for the parents' lineages).
/// </summary>
public enum ParentLineage : byte
{
    Sire = 0,
    Dam  = 1,
}

/// <summary>
/// Phase 6.5 M5 — scent-mask tier suppressing hybrid detection. Maps to
/// the consumable items in <c>items.json</c>:
///   None      — no mask active
///   Basic     — scent_mask_basic; advantage on PC Deception roll
///   Military  — scent_mask_military; auto-suppresses scent detection
///   DeepCover — scent_mask_deep_cover; auto-suppresses, even Superior Scent
///
/// Per the Phase 6.5 plan §4.7. Phase 8's clock + rest model adds
/// time-based expiry; M5 carries the tier as static state.
/// </summary>
public enum ScentMaskTier : byte
{
    None      = 0,
    Basic     = 1,
    Military  = 2,
    DeepCover = 3,
}
