# Flujo de Autenticación para Vue — QSR Platform API

Base URL: `https://tudominio.com/api`  
Todos los endpoints devuelven `Content-Type: application/json`.

---

## 1. Login

### `POST /api/default/login/acceso`

**Público** — no requiere token.

#### Body

```json
{
  "usuarioAlias":    "admin",
  "usuarioPassword": "MiPassword1!",
  "usuarioRecordar": "N"
}
```

| Campo | Tipo | Requerido | Valores |
|---|---|---|---|
| `usuarioAlias` | string | ✅ | Alias o nombre de usuario |
| `usuarioPassword` | string | ✅ | Contraseña |
| `usuarioRecordar` | string | ❌ | `"S"` (token de larga duración) \| `"N"` (expiración estándar) |

#### Respuesta exitosa `200`

```json
{
  "success":    true,
  "message":    "Excelente logueo con éxito.",
  "token":      "1|AbCdEfGhIjKlMnOpQrStUvWxYz...",
  "token_type": "Bearer",
  "expira_en":  "2026-07-01T00:00:00+00:00",
  "url":        "/empresa-selector"
}
```

> `expira_en` es `null` cuando el token no expira (modo sin `sanctum.expiration`).  
> `url` es la ruta a la que el flujo Blade redirige — en Vue **ignórala** y sigue el flujo de empresa descrito abajo.

#### Respuesta de error `422`

```json
{
  "success":  false,
  "required": true,
  "message":  { "usuarioAlias": ["Usuario o contraseña incorrectos."] }
}
```

#### Qué hacer en Vue tras login exitoso

```js
// 1. Guardar el token
localStorage.setItem('fsg_token', data.token)

// 2. Ir al flujo de empresa (ver sección 2)
await cargarEmpresaActiva()
```

---

## 2. Selección de empresa activa (post-login)

Después del login, el frontend **debe** determinar con qué empresa va a trabajar el usuario y guardar su ID para enviarlo en cada request como header `X-Empresa-Id`.

### 2.1 Obtener empresas del usuario

#### `GET /api/default/inicio/mis-empresas`

**Requiere** `Authorization: Bearer <token>`

#### Respuesta `200`

```json
{
  "success": true,
  "total":   2,
  "data": [
    {
      "id":     "MQ==",
      "nombre": "FSG",
      "razon":  "Four Sides Group S.A. de C.V.",
      "rfc":    "FSG123456ABC",
      "tipo":   "Interna"
    },
    {
      "id":     "Mg==",
      "nombre": "QSR",
      "razon":  "QSR Operations S.A. de C.V.",
      "rfc":    "QRS654321XYZ",
      "tipo":   "Externa"
    }
  ]
}
```

> El campo `id` está en **base64**. Para obtener el entero: `atob("Mg==")` → `"2"` → `parseInt("2", 10)` → `2`.  
> Guarda siempre el entero en el store, no el base64.

### 2.2 Confirmar empresa seleccionada

#### `POST /api/default/inicio/seleccionar-empresa`

**Requiere** `Authorization: Bearer <token>`

```json
{ "idEmpresa": "Mg==" }
```

> Envía el `id` en base64 tal como lo devolvió `mis-empresas`.

#### Respuesta `200`

```json
{
  "success": true,
  "url":     "/activar-empresa?e=Mg=="
}
```

> El campo `url` es para el puente de sesión Blade — en Vue **ignóralo**.  
> Si `success` es `true`, la empresa quedó validada. Guarda el entero en el store.

#### Respuesta `403`

```json
{ "success": false, "message": "Empresa no asignada al usuario." }
```

### 2.3 Lógica de selección en Vue

```js
async function cargarEmpresaActiva() {
  const { data } = await api.get('/default/inicio/mis-empresas')
  const empresas = data.data

  if (empresas.length === 0) {
    // Sin empresas — mostrar error o pantalla de contacto admin
    router.push('/sin-empresa')
    return
  }

  if (empresas.length === 1) {
    // Una sola empresa — selección automática silenciosa
    await seleccionarEmpresa(empresas[0])
    router.push('/inicio')
    return
  }

  // Múltiples empresas — mostrar pantalla de selección
  store.empresas = empresas
  router.push('/seleccionar-empresa')
}

async function seleccionarEmpresa(empresa) {
  await api.post('/default/inicio/seleccionar-empresa', { idEmpresa: empresa.id })

  // Guardar el entero en el store / localStorage
  const idInt = parseInt(atob(empresa.id), 10)
  store.idEmpresaActiva = idInt
  localStorage.setItem('idEmpresaActiva', idInt)
}
```

### 2.4 Enviar empresa en cada request

Configura el interceptor de axios **una sola vez** al inicializar la app:

```js
// src/plugins/axios.js
import axios from 'axios'

const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
})

api.interceptors.request.use(config => {
  const token    = localStorage.getItem('fsg_token')
  const empresa  = localStorage.getItem('idEmpresaActiva')

  if (token)   config.headers['Authorization'] = `Bearer ${token}`
  if (empresa) config.headers['X-Empresa-Id']  = empresa

  return config
})

export default api
```

> El backend valida en cada request que el `X-Empresa-Id` pertenezca al usuario autenticado. Si mandas un ID que el usuario no tiene asignado, el backend usa su primera empresa como fallback.

---

## 3. Logout

### `POST /api/default/login/logout`

**Requiere** `Authorization: Bearer <token>`

No requiere body.

#### Respuesta `200`

```json
{ "success": true, "message": "Sesion cerrada correctamente" }
```

#### En Vue

```js
async function logout() {
  await api.post('/default/login/logout')
  localStorage.removeItem('fsg_token')
  localStorage.removeItem('idEmpresaActiva')
  store.$reset()
  router.push('/login')
}
```

---

## 4. Recuperación de contraseña

El flujo tiene 3 pasos: verificar email → validar código → nueva contraseña.

---

### Paso 1 — Verificar email

#### `POST /api/default/login/validar-usuario`

**Público.**

```json
{ "usuarioEmail": "usuario@ejemplo.com" }
```

#### Respuesta exitosa `200`

```json
{
  "success":    true,
  "usuario_id": "MQ==",
  "message":    "Se envió un código de verificación a tu correo."
}
```

> Guarda `usuario_id` (base64) — lo necesitas en el paso 2.

#### Respuesta de error `200` (éxito falso)

```json
{ "success": false, "message": "No se encontró ningún usuario con ese correo." }
```

---

### Paso 2 — Validar código de 6 dígitos

El usuario recibe un código por correo. Se envía dígito a dígito.

#### `POST /api/default/login/validar-codigo`

**Público.**

```json
{
  "idUsuario": "MQ==",
  "digito1": "4",
  "digito2": "7",
  "digito3": "2",
  "digito4": "9",
  "digito5": "1",
  "digito6": "5"
}
```

#### Respuesta exitosa `200`

```json
{
  "success":         true,
  "url":             "/default/login/password-recovery/reset",
  "usuario_id":      "MQ==",
  "_token_reseteo":  "abc123xyz..."
}
```

> Guarda `usuario_id` y `_token_reseteo` — los necesitas en el paso 3.  
> El campo `url` es para la vista Blade — en Vue ignóralo, navega a tu ruta de reset.

#### Respuesta de error `200`

```json
{ "success": false, "message": "Código incorrecto o expirado." }
```

### Reenviar código

#### `POST /api/default/login/solicitar-nuevo-codigo`

**Público.**

```json
{ "idUsuario": "MQ==" }
```

#### Respuesta `200`

```json
{ "success": true, "message": "Se envió un nuevo código a tu correo." }
```

---

### Paso 3 — Nueva contraseña

#### `POST /api/default/login/actualizar-contrasena`

**Público** — el `_token_reseteo` actúa como credencial temporal.

```json
{
  "idUsuario":                    "MQ==",
  "_token_reseteo":               "abc123xyz...",
  "usuarioPassword":              "NuevaPassword1!",
  "usuarioPassword_confirmation": "NuevaPassword1!"
}
```

#### Reglas de la contraseña

| Regla | Detalle |
|---|---|
| Mínimo 8 caracteres | |
| Al menos una mayúscula | |
| Al menos una minúscula | |
| Al menos un número | |
| Al menos un símbolo | `!@#$%^&*` etc. |

#### Respuesta exitosa `200`

```json
{ "success": true, "message": "Contraseña actualizada correctamente." }
```

#### Respuesta de error `422`

```json
{
  "success": false,
  "status":  422,
  "message": "Tienes errores de validación",
  "errors": {
    "usuarioPassword": ["La contraseña debe contener al menos un símbolo (carácter especial)."]
  }
}
```

> Después de actualizar la contraseña, redirige al login — el token de reseteo es de un solo uso.

---

## 5. Resumen del flujo completo

```
Login (/acceso)
  └─ Guardar token en localStorage
  └─ GET /mis-empresas
      ├─ 1 empresa  → POST /seleccionar-empresa → guardar idEmpresaActiva → /inicio
      └─ N empresas → mostrar selector
                        └─ usuario elige
                           └─ POST /seleccionar-empresa → guardar idEmpresaActiva → /inicio

Cada request posterior:
  Header: Authorization: Bearer <token>
  Header: X-Empresa-Id: <idEmpresaActiva>   ← entero, no base64

Recuperación de contraseña:
  POST /validar-usuario  (email)
    └─ POST /validar-codigo  (6 dígitos)
         └─ POST /actualizar-contrasena  (nueva pass + token_reseteo)
              └─ Redirigir al login
```

---

## 6. Manejo de errores comunes

| Status | Causa | Acción recomendada |
|---|---|---|
| `401` | Token inválido o expirado | Limpiar localStorage y redirigir al login |
| `403` | Sin permiso para ese recurso o empresa no asignada | Mostrar mensaje de acceso denegado |
| `422` | Validación fallida | Mostrar `errors` del response en el formulario |
| `429` | Rate limit (60 req/min) | Esperar y reintentar con back-off |
| `503` / `500` | Error del servidor | Mostrar mensaje genérico y registrar en tu logger |
