# (CU-03-007) Instructor finaliza sesión en vivo - Documentación Completa

## Descripción de la Tarea

**Actor:** Instructor  
**Precondiciones:** Sesión en estado "En Vivo"  
**Postcondiciones:** Sesión finalizada, asistencia registrada, grabación disponible (si aplica)

### Objetivo
Registrar de forma clara y completa todo lo realizado para que la sesión en vivo quede:
- finalizada correctamente en el sistema
- marcada como `completed`
- con duración real registrada
- con grabación descargada y disponible
- con asistencia registrada para los estudiantes
- con trazabilidad de callbacks de BBB

### Flujo Principal
1. Instructor click en "Finalizar Sesión" dentro de BBB
2. Sistema BBB cierra la sala
3. Webhook de BBB notifica a Laravel
4. Sistema:
   - Actualiza estado a "Completada"
   - Registra duración real
   - Si hay grabación: espera procesamiento de BBB, descarga y almacena video, actualiza recording_url
   - Marca attended = true para estudiantes que estuvieron presentes
5. Sistema envía notificaciones:
   - A estudiantes asistentes: "Gracias por participar. La grabación estará disponible pronto."
   - A estudiantes ausentes: "Te perdiste la sesión [título]. La grabación ya está disponible."
6. Actualiza estadísticas del instructor

## Lo que se agregó

### Nuevos Archivos
- `app/Notifications/LiveSessionEnded.php` - Notificación por email para estudiantes cuando finaliza la sesión
- `routes/webhooks.php` - Rutas dedicadas para webhooks de BBB sin middleware CSRF
- `app/Console/Commands/CompleteLiveSession.php` - Comando Artisan para finalizar manualmente una sesión
- `test-webhooks.php` - Script de prueba para comprobar que los endpoints de webhook son accesibles
- `check-sessions.php` - Script para ver el estado actual de todas las sesiones por tenant
- `tests/Feature/BigBlueButtonWebhookTest.php` - Pruebas automáticas que validan el comportamiento de los webhooks
- `tests/Feature/UpdateNgrokUrlCommandTest.php` - Test del comando ngrok

### Archivos Modificados
- `app/Http/Controllers/BigBlueButtonWebhookController.php` - Agregados métodos `meetingEnded()`, `recordingReady()` y `testWebhook()`
- `app/Services/BigBlueButtonService.php` - Agregados `getRecordings()` y `downloadRecording()`
- `app/Models/LiveSession.php` - Campos adicionales para grabaciones: `recording_url_bbb`, `recording_url_local`, `recording_duration`
- `app/Models/SessionBooking.php` - Campo `attended` para marcar asistencia
- `config/bigbluebutton.php` - Configuración para callbacks de BBB
- `routes/webhooks.php` - Añadido endpoint de prueba `/webhooks/bbb/test`
- `database/migrations/2026_03_24_175135_add_role_to_users_table.php` - Nueva migración para tabla global users

### Nuevas Funcionalidades
- Webhook handler para finalización de reuniones BBB
- Webhook handler para grabaciones listas
- Actualización automática de estado de sesiones
- Registro de asistencia basado en datos de BBB
- Descarga automática de grabaciones a almacenamiento local
- Sistema de notificaciones por email para estudiantes
- Comando para actualizar URL de ngrok en desarrollo
- Comando para completar sesiones manualmente
- Scripts de verificación y testing

## Variables de Entorno (.env)

Asegúrate de configurar estas variables en tu archivo `.env`:

```env
# BigBlueButton Configuration
BBB_SERVER_BASE_URL=https://bbb.example.com/bigbluebutton/api
BBB_SECURITY_SALT=your-bbb-secret-here

# Webhook Callbacks (Development)
BBB_CALLBACK_URL=https://abc123.ngrok.dev
```

## Flujo de Trabajo Implementado

### 1. Configuración Inicial
- Configurar BBB_SERVER_BASE_URL y BBB_SECURITY_SALT en config/bigbluebutton.php
- Agregar BBB_CALLBACK_URL en .env para desarrollo con ngrok
- Ejecutar `php artisan ngrok:update-url --save` para actualizar URL de callback

### 2. Creación de Sesión en BBB
En `app/Livewire/Instructor/LiveSessions/Create.php` se inyectan los metadatos de callback:
- `meta_endCallbackUrl` → `route('webhooks.bbb.meeting-ended', [], true)`
- `meta_bbb-recording-ready-url` → `route('webhooks.bbb.recording-ready', [], true)`

### 3. Fin de la Reunión en BBB
Cuando el instructor termina la sesión en BBB:
1. BBB envía el callback `meeting-ended`
2. Laravel recibe ese callback en `BigBlueButtonWebhookController::meetingEnded()`
3. El controlador realiza:
   - Validación de `meetingID`
   - Búsqueda de la sesión en el tenant correcto
   - Cambio de `status` a `completed`
   - Cálculo de `recording_duration` si no existe
   - Actualización de asistencia usando `getMeetingInfo()`
   - Envío de notificaciones a estudiantes

### 4. Grabación Lista
Cuando BBB procesa la grabación:
1. BBB envía el callback `recording-ready`
2. `BigBlueButtonWebhookController::recordingReady()`:
   - Recibe `meetingId` y `recordingId`
   - Localiza la sesión con ese `meetingId`
   - Consulta grabaciones con `BigBlueButtonService::getRecordings()`
   - Elige la URL de playback válida
   - Descarga el archivo con `BigBlueButtonService::downloadRecording()`
   - Guarda el archivo en `storage/app/public/recordings/`
   - Actualiza en DB: `recording_url`, `recording_duration`

### 5. Desarrollo del Webhook Controller
- Crear BigBlueButtonWebhookController con métodos meetingEnded y recordingReady
- Implementar búsqueda de tenant por meetingID (soporte multi-tenant)
- Agregar logging detallado para debugging

### 6. Testing
- Crear tests para webhooks usando Pest
- Probar con script test-webhooks.php
- Verificar logs en tiempo real con tail -f storage/logs/laravel.log

## Herramientas Utilizadas

- **Laravel Framework** (v12) - Framework principal
- **BigBlueButton API** - Integración con plataforma de videoconferencias
- **Pest** - Framework de testing
- **ngrok** - Túnel para desarrollo y callbacks
- **Tailwind CSS** - Estilos de UI
- **Filament** - Panel de administración
- **Livewire** - Componentes reactivos
- **Volt** - Templates funcionales para Livewire

## Errores Encontrados Durante el Desarrollo

### 1. Problemas con Multi-Tenancy
**Error:** Los webhooks llegan sin contexto de tenant, causando errores al buscar sesiones.  
**Solución:** Implementar búsqueda iterativa por todos los tenants hasta encontrar la sesión correspondiente. Agregar logs detallados para debugging.

### 2. Webhooks no llegan en desarrollo
**Error:** ngrok tunnel no configurado correctamente, webhooks no llegan a Laravel.  
**Solución:** Crear comando `ngrok:update-url` para automatizar la configuración de BBB_CALLBACK_URL en .env.

### 3. Asistencia no se registra correctamente
**Error:** BBB no proporciona IDs de usuario consistentes en el callback de finalización.  
**Solución:** Usar getMeetingInfo adicional para obtener lista de asistentes reales. Implementar mapeo por userID de BBB.

### 4. Grabaciones no se descargan
**Error:** URLs de grabación expiraban o formato incorrecto.  
**Solución:** Implementar fallback a URL de BBB si descarga local falla. Agregar validación de formatos disponibles.

### 5. Notificaciones duplicadas
**Error:** Múltiples callbacks de BBB causaban envíos repetidos.  
**Solución:** Verificar estado de la sesión antes de enviar notificaciones, solo enviar una vez.

### 6. Callback URL no accesible
**Error:** Firewall, DNS o dominio incorrecto bloqueaban el acceso desde BBB.  
**Solución:** Verificar conectividad con curl y ajustar configuración de ngrok.

### 7. MeetingID mismatch
**Error:** BBB envía un meetingID distinto al bbb_meeting_id guardado en la DB.  
**Solución:** Implementar búsqueda flexible y agregar logs para identificar discrepancias.

## Comandos Utilizados

### Artisan Commands
```bash
# Crear archivos
php artisan make:controller BigBlueButtonWebhookController
php artisan make:notification LiveSessionEnded
php artisan make:command UpdateNgrokUrlCommand
php artisan make:command CompleteLiveSession

# Configuración
php artisan optimize:clear
php artisan ngrok:update-url --save

# Testing
php artisan test --compact --filter=webhook
php artisan test --compact --filter=UpdateNgrokUrlCommandTest

# Completar sesión manualmente
php artisan live-session:complete {session_id} --tenant={tenant_id}
```

### Scripts de Verificación
```bash
# Probar webhooks
php test-webhooks.php

# Ver estado de sesiones
php check-sessions.php

# Consultar sesión en BBB
php bbb-query-session.php <meeting_id>
```

### Comandos de Desarrollo
```bash
# Servidor de desarrollo
php artisan serve

# Ngrok tunnel
ngrok http 8000

# Logs en tiempo real
tail -f storage/logs/laravel.log | grep 'BBB Webhook'

# Test manual de webhook
curl -X POST 'http://localhost:8000/webhooks/bbb/test' -d 'test=manual'
```

### Comandos SSH (para debugging en servidor BBB)
```bash
# Conectar al servidor BBB
ssh -v root@89.167.59.25 -i ~/.ssh/id_futurum_bbb_new

# Ver logs de BBB
tail -f /var/log/bigbluebutton/bbb-web.log
```

## Testing y Verificación

### Tests Automáticos
- `tests/Feature/BigBlueButtonWebhookTest.php` - Pruebas de webhooks y servicio BBB
- `tests/Feature/UpdateNgrokUrlCommandTest.php` - Test del comando ngrok

### Verificación Manual
1. **Comprobar endpoint de prueba:**
   ```bash
   php test-webhooks.php
   ```
   Debe mostrar URLs de callback configuradas y respuesta exitosa.

2. **Ver estado de sesiones:**
   ```bash
   php check-sessions.php
   ```
   Muestra sesiones por tenant: live, scheduled, completed.

3. **Forzar finalización manual:**
   ```bash
   php artisan live-session:complete {session_id} --tenant={tenant_id}
   ```

4. **Test de webhook:**
   ```bash
   curl -X POST 'http://localhost:8000/webhooks/bbb/test' -d 'test=manual'
   ```

5. **Revisar logs:**
   ```bash
   tail -f storage/logs/laravel.log | grep 'BBB Webhook'
   ```

## Posibles Problemas y Soluciones

1. **Callback no llega:** Verificar que `meta_endCallbackUrl` se envía a BBB
2. **URL no accesible:** Revisar firewall, DNS, configuración de ngrok
3. **MeetingID diferente:** BBB puede enviar meetingID distinto al guardado
4. **Endpoint mal configurado:** Verificar rutas en `routes/webhooks.php`
5. **Tenant no encontrado:** Webhook llega sin contexto de tenant

## Detalle Técnico de Callbacks

### `meeting-ended`
Parámetros: `meetingID`, `recordingmarks`
- Valida que `meetingID` coincida con `bbb_meeting_id`
- Cambia status a `completed`
- Registra duración y asistencia

### `recording-ready`
Parámetros: `meetingId`, `recordingId`
- Busca grabación en BBB
- Descarga video a almacenamiento local
- Actualiza `recording_url` y `recording_duration`

## Consideraciones Técnicas

- **Multi-Tenancy:** Los webhooks deben buscar en todos los tenants ya que llegan sin contexto
- **Asincronía:** Las grabaciones pueden tardar en procesarse, usar callbacks separados
- **Fallbacks:** Siempre mantener URL de BBB como respaldo si descarga local falla
- **Logging:** Logs extensivos para debugging en producción
- **Queue:** Notificaciones enviadas a través de queue para mejor performance
- **Seguridad:** Webhooks sin CSRF middleware para permitir callbacks externos

## Resultado Esperado

Al finalizar correctamente, el sistema debe tener:
- ✅ Sesión marcada como `completed`
- ✅ Duración real registrada en `recording_duration`
- ✅ Grabación descargada y `recording_url` disponible
- ✅ Notificaciones enviadas a estudiantes
- ✅ Asistencia registrada para participantes
- ✅ Logs claros para debugging

## Próximos Pasos

- Implementar actualización automática de estadísticas del instructor
- Agregar métricas de participación en tiempo real
- Mejorar detección de asistencia con más datos de BBB
- Implementar notificaciones push además de email
- Agregar soporte para múltiples formatos de grabación
- Implementar retry automático para descargas fallidas
- Agregar dashboard de monitoreo de webhooks</content>
<parameter name="filePath">/Volumes/HP/DevPro/php/futurum-studio/docs/(CU-03-007) Instructor finaliza sesión en vivo - Documentación Completa.md