# Documentación API - Servicio SQL Injector

**Base URL**: `http://localhost:3120/v1`

Este servicio permite la ejecución remota de consultas SQL en tiendas distribuidas mediante un mecanismo de polling, almacenamiento de resultados y consulta de historial.

---

## 1. Consultar Comandos Pendientes (Polling)
Este endpoint es consumido por el cliente (tienda) para saber si tiene algún comando SQL pendiente de ejecutar.

- **Método**: `GET`
- **Ruta**: `/commands`
- **Parámetros (Query)**:
    - `store_id`: ID de la tienda (Requerido).
    - `id_cliente`: ID del cliente (Opcional).

**Ejemplo de Solicitud**:
```http
GET /v1/commands?store_id=44&id_cliente=1
```

**Respuestas**:
- **200 OK**: Se encontró un comando pendiente.
  ```json
  {
      "command_id": 123,
      "sql": "SELECT * FROM users LIMIT 1",
      "privilegio": "READ"
  }
  ```
- **204 No Content**: No hay comandos pendientes.
- **500 Internal Server Error**: Error del servidor.

---

## 2. Crear Nuevo Comando
Permite a un administrador o sistema central poner en cola una instrucción SQL para ser ejecutada por una tienda específica.

- **Método**: `POST`
- **Ruta**: `/commands`
- **Cuerpo (JSON)**:
    - `store_id` (Number): ID de la tienda objetivo (Requerido).
    - `sql` (String): Sentencia SQL a ejecutar (Requerido).
    - `privilegio` (String): Nivel de permiso, por defecto "READ". Opcional.
    - `id_user` (Number): ID del usuario que solicita el comando. Opcional.
    - `id_cliente` (Number): ID del cliente. Opcional.

**Ejemplo de Solicitud**:
```json
{
  "store_id": 44,
  "sql": "SELECT count(*) FROM ventas",
  "privilegio": "READ",
  "id_user": 1,
  "id_cliente": 1
}
```

**Respuesta Exitosa (201 Created)**:
```json
{
    "success": true,
    "message": "Comando creado exitosamente",
    "command_id": 124
}
```

---

## 3. Guardar Resultado de Comando
Este endpoint es utilizado por el cliente (tienda) para reportar el resultado de la ejecución del SQL.

- **Método**: `POST`
- **Ruta**: `/commands/result`
- **Cuerpo (JSON)**:
    - `command_id` (Number): ID del comando ejecutado (Requerido).
    - `result` (Object/Array): El resultado de la consulta SQL. 
    *Nota: Si se envía el cuerpo sin la propiedad `result`, el sistema intentará tomar todo el cuerpo como el resultado.*

**Ejemplo de Solicitud**:
```json
{
  "command_id": 124,
  "result": [
    { "count": 150 }
  ]
}
```

**Respuesta Exitosa (200 OK)**:
```json
{
    "success": true,
    "message": "Resultado guardado correctamente"
}
```

---

## 4. Consultar Estado/Resultado de Comando
Permite consultar si un comando específico ya fue ejecutado y obtener su resultado.

- **Método**: `GET`
- **Ruta**: `/commands/:command_id`
- **Parámetros (Path)**:
    - `command_id`: ID del comando a consultar.

**Ejemplo de Solicitud**:
```http
GET /v1/commands/124
```

**Respuestas**:
- **200 OK**: Comando completado.
  ```json
  {
      "command_id": 124,
      "status": "completed",
      "result": [
          { "count": 150 }
      ],
      "processed_at": "2026-01-13T19:00:00.000Z"
  }
  ```
- **404 Not Found**: El comando no existe o aún no ha sido procesado (estado pendiente).

---

## 5. Historial de Comandos por Usuario
Devuelve una lista de los últimos comandos solicitados por un usuario específico.

- **Método**: `GET`
- **Ruta**: `/commands/user/:id_user`
- **Parámetros (Path)**:
    - `id_user`: ID del usuario.
- **Parámetros (Query)**:
    - `limit`: Cantidad de registros a traer (Default: 50).

**Ejemplo de Solicitud**:
```http
GET /v1/commands/user/1?limit=5
```

**Respuesta Exitosa (200 OK)**:
```json
[
  {
    "command_id": 124,
    "store_id": 44,
    "sql": "SELECT count(*) FROM ventas",
    "privilegio": "READ",
    "estado": "1",
    "fecha_solicitud": "2026-01-13T18:55:00.000Z",
    "fecha_proceso": "2026-01-13T19:00:00.000Z",
    "json_response": [ { "count": 150 } ]
  }
]
```

---

## 6. Estado de Tiendas (Heartbeat)
Devuelve el estado de conectividad de las tiendas basado en su último heartbeat.

- **Método**: `GET`
- **Ruta**: `/stores/status`
- **Parámetros (Query)**:
    - `filter` (String): Filtrar por estado de conectividad. Valores: `online`, `offline`, `all` (Default: `all`).
    - `id_cliente` (Number): Filtrar por ID de cliente. Opcional.

**Estados de Conectividad**:
- **ONLINE**: Último ping hace menos de 2 minutos (120 segundos)
- **DEGRADED**: Último ping entre 2 y 5 minutos (120-300 segundos)
- **OFFLINE**: Último ping hace más de 5 minutos (>300 segundos)

**Ejemplo de Solicitud**:
```http
GET /v1/stores/status?filter=online
GET /v1/stores/status?filter=all&id_cliente=1
```

**Respuesta Exitosa (200 OK)**:
```json
{
  "total": 2,
  "filter_applied": "online",
  "stores": [
    {
      "store_id": 44,
      "id_cliente": 1,
      "instance_id": "sql_inyector",
      "connectivity": "ONLINE",
      "status": "alive",
      "last_ping": "2026-02-09T18:15:30.000Z",
      "seconds_since_ping": 45,
      "extra_info": {
        "message": "Consultando comandos",
        "timestamp": "2026-02-09T18:15:30.000Z"
      }
    },
    {
      "store_id": 370,
      "id_cliente": 1,
      "instance_id": "sql_inyector",
      "connectivity": "OFFLINE",
      "status": "alive",
      "last_ping": "2026-02-09T17:50:00.000Z",
      "seconds_since_ping": 1530,
      "extra_info": null
    }
  ]
}
```

**Notas Importantes**:
- Si una tienda **nunca ha enviado un heartbeat**, NO aparecerá en la respuesta de este endpoint.
- Solo se muestran tiendas que tienen al menos un registro en `tb_store_process_heartbeat` con `process_name = 'sql_inyector'`.
- Para ver tiendas que nunca se han conectado, necesitarías tener una tabla maestra de tiendas y hacer un LEFT JOIN.

---

## Códigos de Estado HTTP

- **200 OK**: Solicitud exitosa
- **201 Created**: Recurso creado exitosamente
- **204 No Content**: Solicitud exitosa sin contenido
- **400 Bad Request**: Parámetros inválidos o faltantes
- **404 Not Found**: Recurso no encontrado
- **500 Internal Server Error**: Error del servidor
