// lua_engine — Lua 5.4 sandbox para evaluar formulas de columnas.
//
// Extraido del playground tables (issue 0081-D).
//
// Features:
//   - Sandbox: io/require/dofile/loadfile/load/package/debug fuera.
//     os reducido a date/time/difftime/clock.
//   - Builtins fn.* (~20 funciones de string/tipo/fecha).
//   - Sintaxis [col_name] preprocesada a row["col_name"].
//   - Auto-`return` si la formula es expresion sin keyword inicial.
//   - Type-aware push: columna Int/Float -> number, Bool -> boolean,
//     String/Date/Json/Auto -> string (heuristica si Auto).
//   - Llamadas recursivas entre derived cols; ciclos cortados con nil.
//
// Thread-safety: NO thread-safe. Una instancia (Engine) por hilo.
// Ver ## Gotchas en lua_engine.md.
#pragma once

#include "core/data_table_types.h"

#include <string>
#include <unordered_map>
#include <vector>

// Forward declaration del C struct de Lua (definido en lua.h).
struct lua_State;

namespace lua_engine {

struct Engine;

// Ciclo de vida del motor (singleton por proceso/hilo).
Engine* get();
void    shutdown();

// Compila el body de la formula y devuelve un id de referencia (>= 0).
// Retorna -1 en error; err_out recibe el mensaje si no es nullptr.
int  compile(Engine* e, const std::string& body, std::string* err_out);

// Libera la referencia compilada.
void release(Engine* e, int id);

// Contexto de fila pasado a eval().
struct RowCtx {
    const char* const* cells       = nullptr;  // row-major flat array
    int                orig_cols   = 0;
    int                row         = 0;
    const std::vector<std::string>*            header_names        = nullptr;
    const std::unordered_map<std::string,int>* name_to_col         = nullptr;

    // Tipos declarados de las cols originales. nullptr -> heuristica Auto.
    const data_table::ColumnType*              types_orig          = nullptr;
    int                                        n_types_orig        = 0;

    // Derived cols + lookup por nombre (retipados y formulas).
    const std::vector<data_table::DerivedColumn>*         derived             = nullptr;
    const std::unordered_map<std::string,int>*            derived_name_to_idx = nullptr;
};

// Evalua la formula compilada sobre el contexto de fila dado.
// Devuelve el resultado como string. En error devuelve "" y escribe en err_out.
std::string eval(Engine* e, int id, const RowCtx& ctx, std::string* err_out);

// Helper expuesto para tests: preprocesa `[col]` -> `row["col"]`
// respetando strings y comentarios. Aplica auto-return si es expresion.
std::string preprocess(const std::string& body);

// Acceso al lua_State subyacente. Uso restringido: tql.cpp parsea chunks
// (return { ... }) y recorre tablas. NO usar para nada que rompa el sandbox.
::lua_State* raw_state();

} // namespace lua_engine
