-- sv_sdf_system_db.lua — Initialisation du schéma SQLite et fonctions CRUD.
-- NE PAS AddCSLuaFile ce fichier.

SDFSystem = SDFSystem or {}
SDFSystem.DB = SDFSystem.DB or {}

-- ─── Schéma ───────────────────────────────────────────────────────────────
local function InitSchema()
    -- Table de persistance des poubelles placées par les admins.
    -- Le cooldown n'est pas persisté (in-memory, reset au restart — acceptable car 5 min).
    -- NOTE : PRAGMA user_version est global à sv.db (partagé entre tous les addons).
    --        On n'utilise pas PRAGMA user_version pour les migrations — on fait de
    --        l'introspection de colonnes si besoin (voir CLAUDE.md).
    local result = sql.Query([[
        CREATE TABLE IF NOT EXISTS sdf_trash_ents (
            id    INTEGER PRIMARY KEY AUTOINCREMENT,
            model TEXT    NOT NULL,
            x     REAL    NOT NULL DEFAULT 0,
            y     REAL    NOT NULL DEFAULT 0,
            z     REAL    NOT NULL DEFAULT 0,
            pitch REAL    NOT NULL DEFAULT 0,
            yaw   REAL    NOT NULL DEFAULT 0,
            roll  REAL    NOT NULL DEFAULT 0
        )
    ]])
    if result == false then
        ErrorNoHalt("[SDFSystem] Erreur création table sdf_trash_ents : " .. (sql.LastError() or "?") .. "\n")
    else
        print("[SDFSystem] DB initialisée.")
    end
end

hook.Add("Initialize", "SDFSystem.InitDB", InitSchema)

-- ─── Insert ───────────────────────────────────────────────────────────────
-- Insère une nouvelle poubelle en DB. Retourne l'id (integer) ou nil.
function SDFSystem.DB.Insert(model, pos, ang)
    -- Valider les floats de position (rejeter NaN/Inf)
    local x = tonumber(pos.x)
    local y = tonumber(pos.y)
    local z = tonumber(pos.z)
    local p = tonumber(ang.p)
    local ya = tonumber(ang.y)
    local r = tonumber(ang.r)

    if not x or not y or not z or not p or not ya or not r then
        ErrorNoHalt("[SDFSystem] DB.Insert : coordonnées invalides\n")
        return nil
    end
    -- Vérifier NaN / Inf (tonumber("nan") est nil en Lua, mais on double-check)
    if x ~= x or y ~= y or z ~= z then
        ErrorNoHalt("[SDFSystem] DB.Insert : coordonnées NaN\n")
        return nil
    end

    local q = string.format(
        "INSERT INTO sdf_trash_ents (model, x, y, z, pitch, yaw, roll) " ..
        "VALUES (%s, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f)",
        sql.SQLStr(model),   -- modèle déjà validé contre la whitelist avant d'arriver ici
        x, y, z, p, ya, r
    )
    local res = sql.Query(q)
    if res == false then
        ErrorNoHalt("[SDFSystem] DB.Insert SQL error : " .. (sql.LastError() or "?") .. "\n")
        return nil
    end

    local id = tonumber(sql.QueryValue("SELECT last_insert_rowid()"))
    return id
end

-- ─── Delete ───────────────────────────────────────────────────────────────
-- Supprime une poubelle par ID. Retourne true ou false.
function SDFSystem.DB.Delete(id)
    id = math.floor(tonumber(id) or 0)
    if id <= 0 then return false end

    local res = sql.Query(string.format("DELETE FROM sdf_trash_ents WHERE id = %d", id))
    if res == false then
        ErrorNoHalt("[SDFSystem] DB.Delete SQL error : " .. (sql.LastError() or "?") .. "\n")
        return false
    end
    return true
end

-- ─── GetAll ───────────────────────────────────────────────────────────────
-- Retourne toutes les lignes (table of rows) ou {} en cas d'erreur.
function SDFSystem.DB.GetAll()
    local rows = sql.Query("SELECT id, model, x, y, z, pitch, yaw, roll FROM sdf_trash_ents ORDER BY id ASC")
    if rows == false then
        ErrorNoHalt("[SDFSystem] DB.GetAll SQL error : " .. (sql.LastError() or "?") .. "\n")
        return {}
    end
    return rows or {}
end
