================================================================================
MIGRACIÓN REACT NATIVE: AUTENTICACIÓN CON JWT (backend Fercogan)
================================================================================
Documento para adaptar el frontend (React Native) a los nuevos endpoints y al
uso del token Bearer. Base URL de ejemplo: https://testapp.digitaltelecom.net

--------------------------------------------------------------------------------
1. RESUMEN DEL CAMBIO
--------------------------------------------------------------------------------
- Antes: el "login" usaba GET /api/usuarios/confirmado/{email} sin contraseña y
  guardaba solo email en AsyncStorage (inseguro).
- Ahora: el login real es POST /api/usuarios/login con email (username) y
  contraseña. El servidor devuelve un JWT que debe enviarse en las peticiones
  protegidas: header Authorization: Bearer <token>.
- La mayoría de rutas /api/* (remates, lotes, pujas, etc.) requieren JWT salvo
  las excepciones listadas abajo.

--------------------------------------------------------------------------------
2. ENDPOINTS PÚBLICOS (sin Authorization)
--------------------------------------------------------------------------------
POST   /api/usuarios/login          → login (body JSON)
POST   /api/usuarios/registrar      → registro
GET    /api/usuarios/confirmado/{username} → solo verificación registro/aprobado
                                         (útil en flujo signup; no sustituye login)
GET    /auth/verificar/{username}   → mismo concepto que confirmado (signup)
GET    /auth/existe/{username}      → según implementación actual
OPTIONS /**                      → CORS preflight
/ws/** , /contador/**            → según necesidad (actualmente públicos)

--------------------------------------------------------------------------------
3. LOGIN (SIGN IN) — REEMPLAZA confirmado + AsyncStorage sin token
--------------------------------------------------------------------------------
Método: POST
URL:    {BASE_URL}/api/usuarios/login
Headers:
  Content-Type: application/json

Body (JSON):
{
  "username": "<email del usuario>",
  "password": "<contraseña en texto plano; va por HTTPS>"
}

Respuesta 200 (JSON) — guardar estos valores en AsyncStorage:
{
  "token": "<JWT>",
  "tokenType": "Bearer",
  "expiresInMs": 86400000,
  "username": "...",
  "userId": 1,
  "rolId": 1,
  "authenticated": true,
  "confirmed": true
}

Errores:
- 401 + { "error": "Credenciales inválidas" } → usuario inexistente o contraseña incorrecta
- 403 + { "error": "Usuario pendiente de aprobación" } → existe pero aún no aprobado

Acciones en el cliente tras 200:
1) AsyncStorage.setItem("authToken", data.token);
2) AsyncStorage.setItem("usuario", data.username);
3) AsyncStorage.setItem("rol", String(data.rolId));   // ya no hace falta GET /rol/{email}
4) AsyncStorage.setItem("isLoggedIn", "true");
5) Opcional: guardar userId para depuración.

NO guardar la contraseña en AsyncStorage.

--------------------------------------------------------------------------------
4. SESIÓN ACTUAL / USUARIO LOGUEADO
--------------------------------------------------------------------------------
GET {BASE_URL}/api/usuarios/me
Headers:
  Authorization: Bearer <authToken>
  Accept: application/json

Respuesta 200 ejemplo:
{
  "username": "...",
  "userId": 1,
  "rolId": 1,
  "confirmed": true
}

Usar al abrir la app para validar que el token sigue siendo válido; si 401,
limpiar AsyncStorage y volver a pantalla de login.

--------------------------------------------------------------------------------
5. PETICIONES PROTEGIDAS (remates, pujas, lotes, cabañas, etc.)
--------------------------------------------------------------------------------
En TODAS las llamadas fetch/axios a /api/... (excepto login, registrar,
confirmado y auth/verificar según corresponda), añadir:

headers: {
  "Content-Type": "application/json",
  "Authorization": "Bearer " + (await AsyncStorage.getItem("authToken"))
}

Si el servidor responde 401, el token expiró o es inválido: cerrar sesión en
cliente (borrar authToken, isLoggedIn) y redirigir a login.

--------------------------------------------------------------------------------
6. SIGN UP (REGISTRO) — CAMBIOS MÍNIMOS
--------------------------------------------------------------------------------
- GET /auth/verificar/{email} puede seguir usándose sin token para decidir si
  el usuario ya existe o está aprobado (flujo actual).
- POST /api/usuarios/registrar sigue siendo público; body igual que antes
  (username=email, password, celular, ci, nombre, rol).

Tras registro exitoso, el usuario sigue pendiente de aprobación: NO recibirá
JWT válido para app hasta que un admin apruebe; el login con POST /login
devolverá 403 mientras tanto.

--------------------------------------------------------------------------------
7. EJEMPLO handleSignIn (lógica sugerida, pseudocódigo)
--------------------------------------------------------------------------------
async function handleSignIn() {
  setLoading(true);
  setError("");
  if (!validateEmail(email)) { setError("Email inválido"); setLoading(false); return; }

  const res = await fetch(BASE + "/api/usuarios/login", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ username: email, password: password }),
  });

  const data = await res.json().catch(() => ({}));

  if (res.status === 401) {
    setError(data.error || "Credenciales inválidas");
    setLoading(false);
    return;
  }
  if (res.status === 403) {
    setError(data.error || "Cuenta pendiente de aprobación");
    setLoading(false);
    return;
  }
  if (!res.ok) {
    setError("Error de servidor");
    setLoading(false);
    return;
  }

  await AsyncStorage.setItem("authToken", data.token);
  await AsyncStorage.setItem("usuario", data.username);
  await AsyncStorage.setItem("rol", String(data.rolId));
  await AsyncStorage.setItem("isLoggedIn", "true");
  navigation.replace("RematesList");
  setLoading(false);
}

Eliminar: GET confirmado/{email} como sustituto del login, y la llamada
separada a GET /api/usuarios/rol/{email} tras login (los datos vienen en la
respuesta del login).

--------------------------------------------------------------------------------
8. VARIABLES DE ENTORNO BACKEND (operaciones)
--------------------------------------------------------------------------------
En el servidor, definir JWT_SECRET (cadena larga y aleatoria, mínimo 32 bytes
en UTF-8) y opcionalmente JWT_EXPIRATION_MS. El valor por defecto en
application.properties es solo para desarrollo.

================================================================================
FIN DEL DOCUMENTO
================================================================================
