-- cl_init.lua — Rendu 3D2D côté client du SENT sdf_trash.
-- États : disponible / cooldown / fouille (barre + skill-check HUD).
-- Particules (mouches/poussière) pendant la fouille.
-- Flash de rareté après complétion.

include("shared.lua")

-- ─── Thème / fonts (lazy — DBALib peut charger après ce fichier) ─────────
local FALLBACK_PALETTE = {
    bg       = { surface = Color(16, 22, 34), elevated = Color(26, 37, 64) },
    gold     = { base = Color(212, 175, 55), light = Color(240, 216, 120) },
    text     = { primary = Color(232, 236, 240), secondary = Color(106, 117, 133) },
    semantic = {
        success = Color(95, 192, 128),
        warning = Color(212, 175, 55),
        danger  = Color(200, 85, 107),
        info    = Color(56, 139, 253),
    },
}

local function GetTheme()
    if DBALib and DBALib.Theme and DBALib.Theme.palette then
        return DBALib.Theme.palette
    end
    return FALLBACK_PALETTE
end

local function GetFontBody()
    if DBALib and DBALib.Fonts and DBALib.Fonts.Body_md then return DBALib.Fonts.Body_md end
    return "DermaDefault"
end

local function GetFontSmall()
    if DBALib and DBALib.Fonts and DBALib.Fonts.Body_sm then return DBALib.Fonts.Body_sm end
    return "DermaDefault"
end

-- ─── Render group ────────────────────────────────────────────────────────
-- Force RENDERGROUP_BOTH pour que DrawTranslucent() soit appelé.
function ENT:Initialize()
    self.RenderGroup = RENDERGROUP_BOTH
    -- État particules.
    self._partAngles = {}
    for i = 1, (SDFSystem.Config.Immersion.ParticleCount or 5) do
        self._partAngles[i] = math.random() * math.pi * 2
    end
    self._nextPartUpdate = 0
end

function ENT:Draw()
    self:DrawModel()
end

function ENT:DrawTranslucent()
    self:Draw3D2D()
    self:DrawParticles()
end

-- ─── Helper durée ─────────────────────────────────────────────────────────
local function FormatRemaining(secs)
    secs = math.max(0, math.ceil(secs))
    if DBALib and DBALib.Format and DBALib.Format.Duration then
        return DBALib.Format.Duration(secs)
    end
    if secs >= 60 then
        local m = math.floor(secs / 60)
        return string.format("%dm %02ds", m, secs - m * 60)
    end
    return secs .. "s"
end

-- ─── Couleur de rareté ────────────────────────────────────────────────────
local function GetRarityColor(rarityIdx)
    local rarities = SDFSystem.Config.Rarities
    local r = rarities[rarityIdx + 1]  -- rarityIdx est 0-based
    if r and r.colorFn then
        return r.colorFn()
    end
    return GetTheme().gold.base
end

-- ─── Particules côté client ───────────────────────────────────────────────
-- Sprites sombres orbitant au-dessus de la poubelle pendant la fouille.
-- Rendu dans un cam.Start3D2D séparé, throttlé.
function ENT:DrawParticles()
    local cfg = SDFSystem.Config.Immersion
    if not cfg.ParticlesEnabled then return end

    local searchEnd  = self:GetSearchEnd()
    local searcher   = self:GetSearcher()
    local now        = CurTime()

    -- N'afficher les particules que pendant la fouille.
    if searchEnd <= 0 or now >= searchEnd or not IsValid(searcher) then return end

    local localPly = LocalPlayer()
    if not IsValid(localPly) then return end
    if localPly:Team() ~= TEAM_HOBO then return end

    -- Distance-cull.
    local maxDist = SDFSystem.Config.DrawDistance or 400
    if self:GetPos():DistToSqr(localPly:GetPos()) > maxDist * maxDist then return end

    -- Mise à jour des angles (orbite).
    local dt = math.min(FrameTime(), 0.05)
    local speed  = (cfg.ParticleSpeed or 0.8) * math.pi * 2 * dt
    local radius = cfg.ParticleRadius or 18
    local zOff   = cfg.ParticleZOffset or 52
    local size   = cfg.ParticleSize or 4
    local color  = cfg.ParticleColor or Color(60, 50, 40, 180)

    local partCount = cfg.ParticleCount or 5
    for i = 1, partCount do
        self._partAngles[i] = (self._partAngles[i] or 0) + speed * (1.0 + i * 0.15)
    end

    -- Rendu via 3D2D billboard centré sur la poubelle + offset Z.
    local renderPos = self:GetPos() + Vector(0, 0, zOff)
    local renderAng = (renderPos - localPly:EyePos()):Angle()
    renderAng:RotateAroundAxis(renderAng:Up(), -90)
    renderAng:RotateAroundAxis(renderAng:Forward(), 90)

    cam.Start3D2D(renderPos, renderAng, 0.12)
        for i = 1, partCount do
            local a   = self._partAngles[i]
            local px  = math.cos(a) * radius
            local py  = math.sin(a) * (radius * 0.5)   -- ellipse aplatie sur Y
            -- Sprite simple : carré coloré semi-transparent.
            draw.RoundedBox(2, px - size, py - size, size * 2, size * 2, color)
        end
    cam.End3D2D()
end

-- ─── Rendu 3D2D (état global + flash rareté) ──────────────────────────────
function ENT:Draw3D2D()
    local localPly = LocalPlayer()
    if not IsValid(localPly) then return end
    if localPly:Team() ~= TEAM_HOBO then return end

    local distSqr = self:GetPos():DistToSqr(localPly:GetPos())
    local maxDist = SDFSystem.Config.DrawDistance or 400
    if distSqr > maxDist * maxDist then return end

    local now = CurTime()
    local pal = GetTheme()

    local renderPos = self:GetPos() + Vector(0, 0, 55)
    local renderAng = (renderPos - localPly:EyePos()):Angle()
    renderAng:RotateAroundAxis(renderAng:Up(), -90)
    renderAng:RotateAroundAxis(renderAng:Forward(), 90)

    local searchEnd     = self:GetSearchEnd()
    local searcher      = self:GetSearcher()
    local cooldownEnd   = self:GetCooldownEnd()
    local flashTime     = self:GetRarityFlashTime()
    local lastRarityIdx = self:GetLastRarity()
    local duration      = SDFSystem.Config.SearchDuration or 10

    -- ─── Flash de rareté (1.5s après completion) ───────────────────────
    local flashAge = (flashTime > 0) and (now - flashTime) or 999
    if flashAge >= 0 and flashAge < 1.5 then
        local flashAlpha = math.max(0, 1.0 - flashAge / 1.5)
        local rarityCol  = GetRarityColor(lastRarityIdx)
        cam.Start3D2D(renderPos, renderAng, 0.13)
            local bw, bh = 200, 36
            local bx, by = -bw / 2, -bh / 2
            draw.RoundedBox(8, bx, by, bw, bh,
                ColorAlpha(rarityCol, math.floor(200 * flashAlpha)))
        cam.End3D2D()
    end

    -- ─── État 1 : fouille en cours ────────────────────────────────────
    if searchEnd > 0 and now < searchEnd and IsValid(searcher) then
        local searchStart = self:GetSearchStart()
        local progress    = 0
        if searchStart > 0 then
            progress = math.Clamp((now - searchStart) / duration, 0, 1)
        end

        cam.Start3D2D(renderPos, renderAng, 0.12)
            local bw, bh = 220, 46
            local bx, by = -bw / 2, -bh / 2

            draw.RoundedBox(6, bx, by, bw, bh, ColorAlpha(pal.bg.surface, 220))
            draw.SimpleText("Recherche en cours...", GetFontBody(), 0, by + 7,
                pal.text.primary, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)

            local barX, barY, barW, barH = bx + 10, by + 28, bw - 20, 10
            draw.RoundedBox(4, barX, barY, barW, barH, ColorAlpha(pal.bg.elevated, 255))
            if progress > 0 then
                draw.RoundedBox(4, barX, barY, math.floor(barW * progress), barH, pal.gold.base)
            end
        cam.End3D2D()
        return
    end

    -- ─── État 2 : cooldown ───────────────────────────────────────────
    if cooldownEnd > 0 and now < cooldownEnd then
        cam.Start3D2D(renderPos, renderAng, 0.10)
            local bw, bh = 240, 46
            local bx, by = -bw / 2, -bh / 2

            draw.RoundedBox(6, bx, by, bw, bh, ColorAlpha(pal.bg.surface, 210))
            draw.SimpleText("Indisponible", GetFontSmall(), 0, by + 8,
                pal.semantic.danger, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
            draw.SimpleText(FormatRemaining(cooldownEnd - now), GetFontBody(), 0, by + 24,
                pal.text.primary, TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP)
        cam.End3D2D()
        return
    end

    -- ─── État 3 : disponible ─────────────────────────────────────────
    cam.Start3D2D(renderPos, renderAng, 0.11)
        local bw, bh = 160, 30
        local bx, by = -bw / 2, -bh / 2
        draw.RoundedBox(6, bx, by, bw, bh, ColorAlpha(pal.bg.surface, 190))
        draw.SimpleText("Fouillable", GetFontBody(), 0, 0,
            pal.gold.base, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    cam.End3D2D()
end
