-- cl_sdf_system_ui.lua — Menu admin (onglet Placer + onglet Gérer).
-- Utilise exclusivement DBALib.UI. DModelPanel est encapsulé dans des Cards
-- (seule exception autorisée car DBALib n'a pas de model picker natif).

-- IMPORTANT : ne pas faire de early-return au top level (ordre de chargement GMod).
-- On vérifie DBALib lazily à l'intérieur des fonctions.

SDFSystem = SDFSystem or {}

local FRAME = nil  -- référence au Frame courant (évite les doublons)

-- ─── Helper : vérification DBALib ────────────────────────────────────────
local function dbaLibReady()
    if DBALib and DBALib.UI then return true end
    ErrorNoHalt("[SDFSystem] DBALib requis — installez addons/_dbalib\n")
    return false
end

-- ─── Onglet "Placer" — Grille de modèles avec preview 3D ─────────────────
local function BuildPlaceTab(body)
    local cfg    = SDFSystem.Config
    local models = cfg.Models
    local pal    = DBALib.Theme.palette
    local S      = DBALib.Scale

    -- ScrollPanel pour la grille.
    local scroll = DBALib.UI.ScrollPanel({
        parent = body,
        w      = body:GetWide() / S(1),
        h      = body:GetTall() / S(1),
    })
    scroll:SetSize(body:GetSize())
    scroll:SetPos(0, 0)

    local canvas = scroll:GetCanvas()

    -- Paramètres de la grille : 3 colonnes.
    local cols   = 3
    local gapX   = S(12)
    local gapY   = S(12)
    local padX   = S(16)
    local availW = body:GetWide() - padX * 2 - S(20)  -- -20 pour la scrollbar
    local cardW  = math.floor((availW - gapX * (cols - 1)) / cols)
    local cardH  = S(180)

    local totalRows = math.ceil(#models / cols)
    canvas:SetTall((cardH + gapY) * totalRows + padX)

    for i, mdl in ipairs(models) do
        local col = (i - 1) % cols
        local row = math.floor((i - 1) / cols)
        local cx  = padX + col * (cardW + gapX)
        local cy  = padX + row * (cardH + gapY)

        -- Conteneur card.
        local card = vgui.Create("DPanel", canvas)
        card:SetPos(cx, cy)
        card:SetSize(cardW, cardH)
        card.Paint = function(self, w, h)
            draw.RoundedBox(6, 0, 0, w, h, pal.bg.elevated or Color(30, 30, 38))
        end

        -- Preview 3D du modèle.
        local preview = vgui.Create("DModelPanel", card)
        preview:SetPos(0, 0)
        preview:SetSize(cardW, cardH - S(36))
        preview:SetModel(mdl)
        -- Caméra auto via la méthode LayoutEntity du DModelPanel.
        function preview:LayoutEntity(ent)
            self:RunAnimation()
        end

        -- Nom court sous la preview.
        local shortName = string.match(mdl, "([^/]+)%.mdl$") or mdl
        local nameLabel = vgui.Create("DLabel", card)
        nameLabel:SetPos(0, cardH - S(36))
        nameLabel:SetSize(cardW, S(16))
        nameLabel:SetText(shortName)
        nameLabel:SetFont(DBALib.Fonts.Body_sm or "DermaDefault")
        nameLabel:SetColor(pal.text.secondary or Color(160, 160, 160))
        nameLabel:SetContentAlignment(5)  -- centre

        -- Bouton "Placer".
        local capturedIdx = i  -- capture pour la closure
        local btn = DBALib.UI.Button({
            label   = "Placer",
            variant = "primary",
            size    = "sm",
            onClick = function()
                -- Envoyer au serveur l'index du model (PAS le path string).
                net.Start("SDFSystem.RequestSpawn")
                    net.WriteUInt(capturedIdx, SDFSystem.MODEL_INDEX_BITS)
                net.SendToServer()
            end,
        })
        btn:SetParent(card)
        btn:SetPos(S(8), cardH - S(30))
        btn:SetSize(cardW - S(16), S(24))
    end
end

-- ─── Onglet "Gérer" — Table des poubelles + actions ──────────────────────
-- La référence est stockée dans SDFSystem pour permettre le rafraîchissement.
local manageTable = nil

function SDFSystem.RefreshManageTab()
    if not IsValid(manageTable) then return end

    local S    = DBALib.Scale
    local inv  = 1 / S(1)           -- conversion pixels → unités base 1080p (Table scale en interne)
    local data = SDFSystem.MenuData or {}

    -- Rows KEYÉES par l'id de colonne (DBALib.UI.Table lit row[col.id]).
    local rows = {}
    for _, entry in ipairs(data) do
        rows[#rows + 1] = {
            id  = entry.dbId,
            mdl = entry.shortName,
            pos = entry.posStr,
        }
    end

    -- DBALib.UI.Table se construit une seule fois (à SetConfig) — on recrée tout
    -- le contenu du conteneur à chaque rafraîchissement.
    manageTable:Clear()

    if #rows == 0 then
        local empty = DBALib.UI.EmptyState({
            title   = "Aucune poubelle placée",
            message = "Utilisez l'onglet 'Placer' pour spawner une poubelle.",
        })
        empty:SetParent(manageTable)
        empty:SetSize(manageTable:GetSize())
        empty:SetPos(0, 0)
        return
    end

    local mW, mH = manageTable:GetSize()

    -- Sélection courante (mise à jour par onSelect ; pas de GetSelected dans l'API).
    local selectedDbId = nil

    local tbl = DBALib.UI.Table({
        parent     = manageTable,
        w          = mW * inv,
        h          = (mH - S(48)) * inv,   -- réserve la bande basse pour les boutons
        filterable = false,
        columns    = {
            { id = "id",  label = "#",        w = 1, sortable = false },
            { id = "mdl", label = "Modèle",   w = 4, sortable = false },
            { id = "pos", label = "Position", w = 4, sortable = false },
        },
        rows       = rows,
        onSelect   = function(row)
            selectedDbId = row and row.id or nil
        end,
    })
    tbl:SetPos(0, 0)

    -- Barre d'actions en bas.
    local btnArea = vgui.Create("DPanel", manageTable)
    btnArea:SetPos(0, mH - S(40))
    btnArea:SetSize(mW, S(40))
    btnArea.Paint = function() end

    -- Bouton Téléport.
    local btnTp = DBALib.UI.Button({
        label   = "Téléport",
        variant = "ghost",
        size    = "sm",
        onClick = function()
            if not selectedDbId then
                DBALib.UI.Notify({ message = "Sélectionnez une poubelle dans la liste.", type = "warning" })
                return
            end
            net.Start("SDFSystem.RequestTeleport")
                net.WriteUInt(math.floor(selectedDbId), SDFSystem.DB_ID_BITS)
            net.SendToServer()
        end,
    })
    btnTp:SetParent(btnArea)
    btnTp:SetPos(0, 0)
    btnTp:SetSize(S(110), S(32))

    -- Bouton Supprimer (avec confirmation).
    local btnDel = DBALib.UI.Button({
        label   = "Supprimer",
        variant = "danger",
        size    = "sm",
        onClick = function()
            if not selectedDbId then
                DBALib.UI.Notify({ message = "Sélectionnez une poubelle dans la liste.", type = "warning" })
                return
            end
            local dbId = selectedDbId
            DBALib.UI.Confirm({
                title   = "Supprimer la poubelle",
                message = "Voulez-vous supprimer la poubelle #" .. tostring(dbId) .. " ? Cette action est irréversible.",
                onYes   = function()
                    net.Start("SDFSystem.RequestRemove")
                        net.WriteUInt(math.floor(dbId), SDFSystem.DB_ID_BITS)
                    net.SendToServer()
                end,
                onNo    = function() end,
            })
        end,
    })
    btnDel:SetParent(btnArea)
    btnDel:SetPos(S(120), 0)
    btnDel:SetSize(S(110), S(32))
end

local function BuildManageTab(body)
    -- Conteneur qui occupe toute la zone de l'onglet.
    manageTable = vgui.Create("DPanel", body)
    manageTable:SetSize(body:GetSize())
    manageTable:SetPos(0, 0)
    manageTable.Paint = function() end

    -- Demander la liste fraîche au serveur.
    net.Start("SDFSystem.RequestMenuSync")
    net.SendToServer()

    -- Affichage placeholder en attendant la réponse.
    local spinner = DBALib.UI.Spinner({ size = DBALib.Scale(32) })
    spinner:SetParent(manageTable)
    local pw, ph = manageTable:GetSize()
    spinner:SetPos((pw - spinner:GetWide()) / 2, (ph - spinner:GetTall()) / 2)
end

-- ─── Ouverture du menu principal ──────────────────────────────────────────
function SDFSystem.OpenAdminMenu()
    if not dbaLibReady() then return end

    -- Empêcher les doublons.
    if IsValid(FRAME) then FRAME:Close(); return end

    DBALib.Sound("ui_open")

    local S = DBALib.Scale

    FRAME = DBALib.UI.Frame({
        title    = "SDFSystem — Administration des poubelles",
        w        = S(720),
        h        = S(520),
        closable = true,
        content  = function(body)
            local tabs = DBALib.UI.Tabs({
                tabs = {
                    {
                        id      = "place",
                        label   = "Placer",
                        builder = function(p)
                            BuildPlaceTab(p)
                        end,
                    },
                    {
                        id      = "manage",
                        label   = "Gérer",
                        builder = function(p)
                            BuildManageTab(p)
                        end,
                    },
                },
                default = "place",
            })
            tabs:SetParent(body)
            tabs:SetSize(body:GetSize())
            tabs:SetPos(0, 0)
        end,
    })

    -- Nettoyage de la référence quand le Frame est fermé.
    local originalOnRemove = FRAME.OnRemove
    FRAME.OnRemove = function(self)
        FRAME = nil
        manageTable = nil
        if originalOnRemove then originalOnRemove(self) end
    end
end
