require "API/DST_API"
require "API/DST_Helpers"

local DST = rawget(_G, "DST") or {}
local ST  = DST and DST.SkillTooltips
if not ST then return end

local KEY = "Fishing"

-----------------------------------------------------------------------
-- Local helpers
-----------------------------------------------------------------------
local function pct(x)
    if not x then return "0%" end
    return tostring(math.floor(x + 0.5)) .. "%"
end

local function pct2DP(x)
    if not x then return "0%" end
    return string.format("%.2f", x) .. "%"
end

local function kg(x)
    if not x then return "—" end
    return string.format("%.1f kg", x)
end

local function getSizeChancesForLevel(lvl)
    local FU = Fishing and Fishing.Utils
    local t = FU and FU.fishSizeChancesBySkillLevel or {
        [0]  = {95, 5, 0},   [1]  = {85, 15, 0}, [2]  = {75, 24, 1},
        [3]  = {70, 25, 5},  [4]  = {60, 30, 10},[5] = {48, 40, 12},
        [6]  = {35, 45, 20}, [7]  = {25, 45, 30},[8] = {20, 40, 40},
        [9]  = {15, 40, 45}, [10] = {10, 40, 50},
    }
    local row = t[lvl] or t[math.max(0, math.min(10, lvl or 0))]

    -- Open Water values (base)
    local sO, mO, bO = row[1], row[2], row[3]

    -- Near Shore adjustment per vanilla:
    --  half of Medium + Big is added to Small; Medium/Big halved
    local sN = sO + (mO + bO) / 2
    local mN = mO / 2
    local bN = bO / 2

    return { sO, mO, bO }, { sN, mN, bN }
end

local function getMaxWeightForLevel(lvl)
    local FU = Fishing and Fishing.Utils
    local limit = FU and FU.skillSizeLimit or {
        [0]=1.4,[1]=1.5,[2]=1.9,[3]=2.2,[4]=2.3,[5]=2.8,[6]=4.5,[7]=9,[8]=27,[9]=32,[10]=45
    }
    return limit[lvl] or limit[math.max(0, math.min(10, lvl or 0))]
end

local function naturalBaitLossPct(level)
    local lose = 19 - (level or 0)
    if lose < 0 then lose = 0 end
    if lose > 19 then lose = 19 end
    return (lose / 20.0) * 100.0
end

local function artificialLureLossPct(level)
    local denom = 30 * ((level or 0) + 1)
    return (1.0 / denom) * 100.0
end

local function tensionTolerance(level, rodCoeff)
    rodCoeff = rodCoeff or 1.0
    local baseWindow = 120 * rodCoeff
    local window     = (120 + 10 * (level or 0)) * rodCoeff
    return window / baseWindow
end

local function castScatterDiv(level)
    return (level or 0) + 1
end

local leafgreen = { color = ST.COLORS.leafgreen }
local BASE_CALORIES = 159
local CALORIE_DIVISOR = 0.4

ST.addContributor(KEY, function(ctx)
    local lvl = ctx.getLevel()

    local maxKg = getMaxWeightForLevel(lvl)
    local maxCal = (maxKg / CALORIE_DIVISOR) * BASE_CALORIES
    local natLoss = naturalBaitLossPct(lvl)
    local artLoss = artificialLureLossPct(lvl)
    local tension = tensionTolerance(lvl, 1.0)
    local scatterDiv = castScatterDiv(lvl)

    -- Catch bounds & distribution
    ctx.add(ST.getText("IGUI_DST_Fishing_val_MaxSize", kg(maxKg), string.format("%.0f", maxCal)), leafgreen)

    ctx.addHeader(ST.getText("IGUI_DST_Core_hdr"))

    -- Gear interaction
    ctx.add(ST.getText("IGUI_DST_Fishing_val_NaturalBaitLoss", pct(natLoss)))
    ctx.add(ST.getText("IGUI_DST_Fishing_val_LureLoss", pct2DP(artLoss)))

    -- Handling
    ctx.add(ST.getText("IGUI_DST_Fishing_val_CastAccuracy", scatterDiv))
    ctx.add(ST.getText("IGUI_DST_Fishing_val_TensionTolerance", string.format("%.2f", tension)))

    local openWater, nearShore = getSizeChancesForLevel(lvl)
    local sO, mO, bO = unpack(openWater)
    local sN, mN, bN = unpack(nearShore)

    ctx.addHeader(ST.getText("IGUI_DST_Fishing_hdr_SizeChances"))
    ctx.add(ST.getText("IGUI_DST_Fishing_val_SizeNearShore", pct(sN), pct(mN), pct(bN)))
    ctx.add(ST.getText("IGUI_DST_Fishing_val_SizeOpenWater", pct(sO), pct(mO), pct(bO)))
end)

ST.addAutoLearnRecipes(KEY)
ST.addUnlockCraftRecipes(KEY)
ST.addUnlockBuildRecipes(KEY)