local ADDON_NAME, RPAL = ...

RPAL.SKILL_SET_VERSION = 6

RPAL.SKILL_SET_CATEGORIES = {
    {
        id = "one_handed",
        name = "ONE-HANDED PROFICIENCY",
        description = "Weapons naturally handled in one hand.",
        skills = {"Axes", "Swords", "Pistols", "Daggers", "Hammers", "Wands", "Shields", "Dual-Wielding"},
    },
    {
        id = "two_handed",
        name = "TWO-HANDED PROFICIENCY",
        description = "Heavy and long weapons requiring two-handed control.",
        skills = {"Greatswords", "Polearms", "Warhammers", "Rifles", "Staves", "Greataxes"},
    },
    {
        id = "armor",
        name = "ARMOR PROFICIENCY",
        description = "Armor weights and protection styles the character is trained to wear effectively.",
        skills = {"Cloth Armor", "Leather Armor", "Mail Armor", "Plate Armor"},
    },
    {
        id = "magic",
        name = "MAGIC PROFICIENCY",
        description = "Magical disciplines the character understands and can practice.",
        skills = {"Cryomancy", "Pyromancy", "Nature Magic", "Void Magic", "Shadow Magic", "Hemomancy", "Necromancy", "Lightwielding", "Arcane", "Elemental Magic"},
    },
    {
        id = "skill",
        name = "SKILL PROFICIENCY",
        description = "Practical character skills used during roleplay.",
        skills = {"Stealth", "Awareness", "Pickpocketing", "Speechcraft", "First Aid"},
    },
    {
        id = "work",
        name = "VOCATIONAL PROFICIENCY",
        description = "Trades, professions and creative disciplines the character has practiced.",
        skills = {"Bartending", "Alchemy", "Engineering", "Smithing", "Woodworking", "Mining", "Writing", "Painting", "Musician"},
    },
}

local function EnsureSkillData()
    if type(RPAL_CHAR_DB) ~= "table" then RPAL_CHAR_DB = {} end
    if type(RPAL_CHAR_DB.skillSet) ~= "table" then RPAL_CHAR_DB.skillSet = {} end
    RPAL_CHAR_DB.skillSet.values = type(RPAL_CHAR_DB.skillSet.values)=="table" and RPAL_CHAR_DB.skillSet.values or {}
    local values=RPAL_CHAR_DB.skillSet.values
    local version=tonumber(RPAL_CHAR_DB.skillSet.version) or 1
    if version<3 then
        for oldName,newName in pairs({Hammer="Hammers",Wand="Wands",Greataxe="Greataxes",["First-Aid"]="First Aid"}) do
            if values[newName]==nil and values[oldName]~=nil then values[newName]=values[oldName] end
            values[oldName]=nil
        end
    end
    RPAL_CHAR_DB.skillSet.version=RPAL.SKILL_SET_VERSION
    return values
end

function RPAL.GetSkillSetValues()
    return EnsureSkillData()
end

function RPAL.GetSkillProficiency(name)
    local values = EnsureSkillData()
    return math.max(0, math.min(5, math.floor(tonumber(values[name]) or 0)))
end

function RPAL.SetSkillProficiency(name, value)
    local values = EnsureSkillData()
    values[name] = math.max(0, math.min(5, math.floor(tonumber(value) or 0)))
    if RPAL.RefreshSkillSet then RPAL.RefreshSkillSet() end
end

function RPAL.AdjustSkillProficiency(name, delta)
    RPAL.SetSkillProficiency(name, RPAL.GetSkillProficiency(name) + (tonumber(delta) or 0))
end

function RPAL.ResetSkillSet()
    local values = EnsureSkillData()
    for k in pairs(values) do values[k] = nil end
    if RPAL.RefreshSkillSet then RPAL.RefreshSkillSet() end
end

EnsureSkillData()

-- ============================================================
-- DnD-like character sheet
-- Optional RP-facing statistics used by ODYN DM Kit stat checks.
-- These values never replace normal Skill Set proficiencies and are entirely
-- player-authored. A DM can request a specific ability check; the participant's
-- local sheet supplies the modifier when they roll.
-- ============================================================
RPAL.CHARACTER_SHEET_VERSION = 1
RPAL.CHARACTER_SHEET_ABILITIES = {
    {id="STR",name="Strength"},
    {id="DEX",name="Dexterity"},
    {id="CON",name="Constitution"},
    {id="INT",name="Intelligence"},
    {id="WIS",name="Wisdom"},
    {id="CHA",name="Charisma"},
}

local SHEET_ABILITY_SET={STR=true,DEX=true,CON=true,INT=true,WIS=true,CHA=true}

local function ClampSheetInt(value,lo,hi,fallback)
    value=tonumber(value)
    if not value or value~=value then return fallback end
    value=math.floor(value+0.00001)
    if value<lo then value=lo elseif value>hi then value=hi end
    return value
end

local function EnsureCharacterSheet()
    if type(RPAL_CHAR_DB)~="table" then RPAL_CHAR_DB={} end
    if type(RPAL_CHAR_DB.characterSheet)~="table" then RPAL_CHAR_DB.characterSheet={} end
    local sheet=RPAL_CHAR_DB.characterSheet
    sheet.version=RPAL.CHARACTER_SHEET_VERSION
    sheet.abilities=type(sheet.abilities)=="table" and sheet.abilities or {}
    for id in pairs(SHEET_ABILITY_SET) do sheet.abilities[id]=ClampSheetInt(sheet.abilities[id],1,30,10) end
    sheet.level=ClampSheetInt(sheet.level,1,20,1)
    sheet.armorClass=ClampSheetInt(sheet.armorClass,0,99,10)
    sheet.maxHP=ClampSheetInt(sheet.maxHP,1,9999,10)
    sheet.speed=ClampSheetInt(sheet.speed,0,999,30)
    sheet.initiativeBonus=ClampSheetInt(sheet.initiativeBonus,-20,20,0)
    return sheet
end

function RPAL.GetCharacterSheet()
    return EnsureCharacterSheet()
end

function RPAL.GetCharacterSheetAbility(id)
    id=tostring(id or ""):upper()
    if not SHEET_ABILITY_SET[id] then return 10 end
    return ClampSheetInt(EnsureCharacterSheet().abilities[id],1,30,10)
end

function RPAL.SetCharacterSheetAbility(id,value)
    id=tostring(id or ""):upper()
    if not SHEET_ABILITY_SET[id] then return false end
    EnsureCharacterSheet().abilities[id]=ClampSheetInt(value,1,30,10)
    if RPAL.RefreshSkillSet then RPAL.RefreshSkillSet() end
    return true
end

function RPAL.AdjustCharacterSheetAbility(id,delta)
    return RPAL.SetCharacterSheetAbility(id,RPAL.GetCharacterSheetAbility(id)+(tonumber(delta) or 0))
end

function RPAL.GetCharacterSheetModifier(id)
    local score=RPAL.GetCharacterSheetAbility(id)
    return math.floor((score-10)/2)
end

function RPAL.GetCharacterSheetAbilityName(id)
    id=tostring(id or ""):upper()
    for _,entry in ipairs(RPAL.CHARACTER_SHEET_ABILITIES or {}) do if entry.id==id then return entry.name end end
    return id
end

function RPAL.GetCharacterSheetDerived(key)
    local sheet=EnsureCharacterSheet()
    if key=="proficiencyBonus" then return 2+math.floor((sheet.level-1)/4) end
    if key=="initiative" then return RPAL.GetCharacterSheetModifier("DEX")+(tonumber(sheet.initiativeBonus) or 0) end
    return sheet[key]
end

function RPAL.SetCharacterSheetDerived(key,value)
    local sheet=EnsureCharacterSheet()
    if key=="level" then sheet.level=ClampSheetInt(value,1,20,sheet.level or 1)
    elseif key=="armorClass" then sheet.armorClass=ClampSheetInt(value,0,99,sheet.armorClass or 10)
    elseif key=="maxHP" then sheet.maxHP=ClampSheetInt(value,1,9999,sheet.maxHP or 10)
    elseif key=="speed" then sheet.speed=ClampSheetInt(value,0,999,sheet.speed or 30)
    elseif key=="initiativeBonus" then sheet.initiativeBonus=ClampSheetInt(value,-20,20,sheet.initiativeBonus or 0)
    else return false end
    if RPAL.RefreshSkillSet then RPAL.RefreshSkillSet() end
    return true
end

function RPAL.AdjustCharacterSheetDerived(key,delta)
    local sheet=EnsureCharacterSheet()
    local current=sheet[key]
    return RPAL.SetCharacterSheetDerived(key,(tonumber(current) or 0)+(tonumber(delta) or 0))
end

function RPAL.ResetCharacterSheet()
    if type(RPAL_CHAR_DB)~="table" then RPAL_CHAR_DB={} end
    RPAL_CHAR_DB.characterSheet=nil
    EnsureCharacterSheet()
    if RPAL.RefreshSkillSet then RPAL.RefreshSkillSet() end
end

EnsureCharacterSheet()

