# Registro

Endpoints del flujo de registro de nuevos usuarios en DeportesCam.
El proceso parte de un número de socio que se valida contra `wd_membresia`
antes de continuar con el registro.

---

## POST /deportescam/registro/validar-socio

Busca el `noSocio` en `wd_membresia.membresiaNo` y verifica que el estado
sea **Activo**. Si es válido retorna los datos de la membresía para
pre-llenar el formulario de registro.

**Autenticación:** No requerida  
**Middleware:** `seguridadFSG`, `throttle:60,1`

### Body (JSON)

| Campo | Tipo | Requerido | Descripción | Ejemplo |
|-------|------|-----------|-------------|---------|
| `noSocio` | string | Sí | Número de socio a validar | `12345` |

```json
{
  "noSocio": "12345"
}
```

### Respuestas

#### 200 — Membresía activa

```json
{
  "success": true,
  "message": "Membresía válida.",
  "data": {
    "idMembresia": "MQ==",
    "membresiaNo": "12345",
    "membresiaTitular": "Juan Pérez",
    "membresiaEmail": "juan@ejemplo.com",
    "membresiaCelular": "5512345678"
  }
}
```

| Campo | Tipo | Descripción |
|-------|------|-------------|
| `success` | bool | `true` cuando la membresía existe y está activa |
| `message` | string | Mensaje descriptivo del resultado |
| `data.idMembresia` | string | ID de la membresía codificado en **Base64** |
| `data.membresiaNo` | string | Número de socio |
| `data.membresiaTitular` | string | Nombre completo del titular |
| `data.membresiaEmail` | string\|null | Correo electrónico registrado |
| `data.membresiaCelular` | string\|null | Número de celular registrado |

> **Nota:** `idMembresia` se retorna en Base64 por seguridad. Para obtener el ID numérico:
> `atob("MQ==")` → `"1"` (JavaScript) / `base64_decode("MQ==")` → `"1"` (PHP)

#### 422 — Socio no encontrado

```json
{
  "success": false,
  "message": "El número de socio no existe."
}
```

#### 422 — Membresía de baja

```json
{
  "success": false,
  "message": "La membresía está dada de baja."
}
```

#### 422 — Membresía inactiva

```json
{
  "success": false,
  "message": "La membresía está inactiva."
}
```

#### 422 — Sin beneficiarios disponibles

```json
{
  "success": false,
  "message": "Todos los beneficiarios de esta membresía ya están registrados."
}
```

#### 422 — Sin beneficiarios en la membresía

```json
{
  "success": false,
  "message": "La membresía no tiene beneficiarios registrados."
}
```

#### 422 — Campo requerido faltante

```json
{
  "success": false,
  "status": 422,
  "message": "Tienes errores de validación",
  "errors": {
    "noSocio": ["El número de socio es requerido."]
  }
}
```

#### 500 — Error interno

```json
{
  "success": false,
  "message": "Descripción del error interno."
}
```

---

## POST /deportescam/registro/enviar-codigo

Genera un código de verificación de **6 caracteres alfanuméricos** (mayúsculas),
lo guarda en `pad_codigoverificacion` con TTL de 10 minutos y lo envía por el
canal indicado. Un código anterior para la misma membresía es eliminado
automáticamente al generar uno nuevo.

**Autenticación:** No requerida  
**Middleware:** `seguridadFSG`, `throttle:60,1`


### Body (JSON)

| Campo | Tipo | Requerido | Descripción | Ejemplo |
|-------|------|-----------|-------------|---------|
| `idMembresia` | string | Sí | ID de membresía en **Base64** (obtenido de `validar-socio`) | `MQ==` |
| `tipo` | string | Sí | Canal de envío: `email` o `whatsapp` | `email` |

```json
{
  "idMembresia": "MQ==",
  "tipo": "email"
}
```

### Respuestas

#### 200 — Código enviado por correo

```json
{
  "success": true,
  "message": "Código enviado al correo electrónico."
}
```

#### 200 — Código generado (WhatsApp pendiente de plantilla)

```json
{
  "success": true,
  "message": "Código generado. La notificación por WhatsApp estará disponible próximamente."
}
```

#### 422 — Membresía sin correo registrado

```json
{
  "success": false,
  "message": "La membresía no tiene correo electrónico registrado."
}
```

#### 422 — Membresía no existe

```json
{
  "success": false,
  "message": "La membresía no existe."
}
```

#### 422 — Campos faltantes o tipo inválido

```json
{
  "success": false,
  "status": 422,
  "message": "Tienes errores de validación",
  "errors": {
    "tipo": ["El tipo debe ser email o whatsapp."]
  }
}
```

#### 500 — Error interno

```json
{
  "success": false,
  "message": "Descripción del error interno."
}
```

---

## POST /deportescam/registro/reenviar-codigo

Invalida el código previo de la membresía, genera uno nuevo y lo reenvía por
el canal indicado. Usar cuando el código anterior expiró o no fue recibido.
La lógica de envío es idéntica a `/enviar-codigo`.

**Autenticación:** No requerida  
**Middleware:** `seguridadFSG`, `throttle:60,1`

### Body (JSON)

| Campo | Tipo | Requerido | Descripción | Ejemplo |
|-------|------|-----------|-------------|---------|
| `idMembresia` | string | Sí | ID de membresía en **Base64** | `MQ==` |
| `tipo` | string | Sí | Canal de envío: `email` o `whatsapp` | `email` |

```json
{
  "idMembresia": "MQ==",
  "tipo": "email"
}
```

### Respuestas

#### 200 — Código reenviado

```json
{
  "success": true,
  "message": "Código enviado al correo electrónico."
}
```

#### 422 / 500

Mismas respuestas de error que `/enviar-codigo`.

---

## POST /deportescam/registro/generar-username

Genera el username automáticamente para el beneficiario seleccionado y lo
retorna al front **sin persistir nada**. El usuario lo verá y confirmará antes
del registro final.

Lógica de generación:
1. Si `beneficiarioCURP` tiene ≥ 10 chars → primeros 10 chars del CURP
2. Si no → `AP(2) + AM(1) + N(1) + YYMMDD`
3. Si el username generado ya está tomado por otra persona → se usa `N(2)` como offset

**Autenticación:** No requerida  
**Middleware:** `seguridadFSG`, `throttle:60,1`

### Body (JSON)

| Campo | Tipo | Requerido | Descripción | Ejemplo |
|-------|------|-----------|-------------|---------|
| `idMembresia` | string | Sí | ID de membresía en **Base64** | `MQ==` |
| `beneficiarioContador` | integer | Sí | Contador del beneficiario seleccionado | `911778` |
| `beneficiarioNombre` | string | Sí | Nombre completo del beneficiario (validación cruzada) | `CENTRO ASTURIANO DE MÉXICO` |

```json
{
  "idMembresia": "MQ==",
  "beneficiarioContador": 911778,
  "beneficiarioNombre": "CENTRO ASTURIANO DE MÉXICO"
}
```

### Respuestas

#### 200 — Username generado

```json
{
  "success": true,
  "message": "Username generado correctamente.",
  "data": {
    "username": "GAMP230618"
  }
}
```

#### 422 — Beneficiario ya registrado

```json
{
  "success": false,
  "message": "Este beneficiario ya tiene un registro activo."
}
```

#### 422 — Nombre no coincide

```json
{
  "success": false,
  "message": "Los datos del beneficiario no coinciden."
}
```

#### 500 — Error interno

```json
{
  "success": false,
  "message": "Descripción del error interno."
}
```

---

## POST /deportescam/registro/crear

Persiste el nuevo usuario en `pad_registropadel` dentro de una transacción con
`lockForUpdate`. Al finalizar crea y retorna el **Bearer token** de Sanctum —
el usuario queda autenticado sin necesidad de hacer login.

Genera automáticamente el `registroPadelNoJugador` (número consecutivo 1, 2, 3…).  
La contraseña se almacena con `Hash::make()` (bcrypt).

**Autenticación:** No requerida  
**Middleware:** `seguridadFSG`, `throttle:60,1`

### Body (JSON)

| Campo | Tipo | Requerido | Descripción | Ejemplo |
|-------|------|-----------|-------------|---------|
| `idMembresia` | string | Sí | ID de membresía en **Base64** | `MQ==` |
| `beneficiarioContador` | integer | Sí | Contador del beneficiario | `911778` |
| `beneficiarioNombre` | string | Sí | Nombre completo del beneficiario | `CENTRO ASTURIANO DE MÉXICO` |
| `username` | string | Sí | Username obtenido de `generar-username` | `GAMP230618` |
| `password` | string | Sí | Mín. 8 chars, mayúsculas, minúsculas, número y carácter especial | `MiPass1!` |
| `password_confirmation` | string | Sí | Confirmación de contraseña | `MiPass1!` |

```json
{
  "idMembresia": "MQ==",
  "beneficiarioContador": 911778,
  "beneficiarioNombre": "CENTRO ASTURIANO DE MÉXICO",
  "username": "GAMP230618",
  "password": "MiPass1!",
  "password_confirmation": "MiPass1!"
}
```

### Respuestas

#### 200 — Registro exitoso

```json
{
  "success": true,
  "message": "Usuario registrado correctamente.",
  "data": {
    "token": "1|abc123xyz..."
  }
}
```

> **Nota:** Guardar el `token` y usarlo como `Authorization: Bearer {token}` en todas las rutas protegidas.

#### 422 — Username alterado

```json
{
  "success": false,
  "message": "El nombre de usuario no es válido."
}
```

#### 422 — Username en uso (concurrencia)

```json
{
  "success": false,
  "message": "El nombre de usuario ya está en uso."
}
```

#### 422 — Contraseña no cumple el formato

```json
{
  "success": false,
  "status": 422,
  "message": "Tienes errores de validación",
  "errors": {
    "password": ["La contraseña debe tener mayúsculas, minúsculas, números y al menos un carácter especial."]
  }
}
```

#### 500 — Error interno

```json
{
  "success": false,
  "message": "Descripción del error interno."
}
```

---

## POST /deportescam/registro/validar-codigo

Verifica el código de 6 caracteres contra `pad_codigoverificacion`. Si es
correcto lo elimina (uso único — si el usuario regresa debe solicitar uno
nuevo) y retorna los beneficiarios de la membresía indicando cuáles ya
tienen un registro activo en `pad_registropadel`.

**Autenticación:** No requerida  
**Middleware:** `seguridadFSG`, `throttle:60,1`

### Body (JSON)

| Campo | Tipo | Requerido | Descripción | Ejemplo |
|-------|------|-----------|-------------|---------|
| `idMembresia` | string | Sí | ID de membresía en **Base64** | `MQ==` |
| `codigo` | string | Sí | Código de verificación de exactamente 6 caracteres | `A1B2C3` |

```json
{
  "idMembresia": "MQ==",
  "codigo": "A1B2C3"
}
```

### Respuestas

#### 200 — Código correcto

```json
{
  "success": true,
  "message": "Código verificado correctamente.",
  "data": {
    "beneficiarios": [
      {
        "contador": 911778,
        "nombre": "CENTRO ASTURIANO DE MÉXICO",
        "tipo": "Titular",
        "registrado_previamente": false
      },
      {
        "contador": 911779,
        "nombre": "JUAN PÉREZ GARCÍA",
        "tipo": "Beneficiario",
        "registrado_previamente": true
      }
    ]
  }
}
```

| Campo | Tipo | Descripción |
|-------|------|-------------|
| `contador` | int | Identificador del beneficiario |
| `nombre` | string | Nombre completo |
| `tipo` | string | `Titular`, `Beneficiario`, etc. |
| `registrado_previamente` | bool | `true` si ya existe en `pad_registropadel` |

#### 422 — Código incorrecto o expirado

```json
{
  "success": false,
  "message": "El código es incorrecto o ha expirado."
}
```

#### 422 — Campos faltantes o código con longitud incorrecta

```json
{
  "success": false,
  "status": 422,
  "message": "Tienes errores de validación",
  "errors": {
    "codigo": ["El código debe tener exactamente 6 caracteres."]
  }
}
```

#### 500 — Error interno

```json
{
  "success": false,
  "message": "Descripción del error interno."
}
```
