# Design: Startup retry, custom stations, and equalizer persistence

## Technical Approach

Keep the existing Provider/ChangeNotifier architecture. Add test seams first, then implement: radio retry in `ServicioRadio`, main-list composition in `EstadoRadio`, and EQ persistence in a dedicated `ServicioEcualizador` using SharedPreferences. Persisted Provider EQ state must not depend on Android equalizer availability.

## Architecture Decisions

| Decision | Choice | Alternatives | Rationale |
|---|---|---|---|
| API retry owner | `ServicioRadio._get()` owns bounded retry and host rotation | Retry only in `EstadoRadio` | Centralizes network resilience for startup and search; avoids duplicated policy. |
| Custom stations home UX | Add `EstadoRadio.emisorasInicio`/similar combining custom + popular when no genre filter | Separate home section | Minimal UI change and reuses `TarjetaEmisora` favorite behavior; separate section can come later. |
| EQ storage | New `ServicioEcualizador` with SharedPreferences JSON | SQLite migration in favorites DB | Main EQ is app-level, not favorite-row data; SharedPreferences is already available and simpler. |
| Station EQ fallback | `Map<uuid, PresetEcualizador>`; absent key means "use main" | Store explicit mode enum per station | Absence is compact and maps naturally to disabling own EQ. |
| Current station source | Fix `ServicioAudio`/handler to assign/clear `emisoraActual` | Track only in `EstadoRadio` | Existing mini player and player screen already read `audio.emisoraActual`; fix the actual source. |

## Data Flow

Startup:

    PluriWaveApp -> EstadoRadio._init()
       -> ServicioEcualizador.cargar() -> preset principal + mapa por emisora
       -> ServicioRadio.obtenerPopulares/Tendencias() -> retry/rotate host
       -> ServicioFavoritos + emisoras_custom.json

Playback:

    UI -> EstadoRadio.reproducir(emisora)
       -> ServicioAudio.reproducir(emisora) sets current station
       -> EstadoRadio selects EQ: presetsPorEmisora[uuid] ?? presetPrincipal
       -> ServicioAudio.aplicarPreset(selected)

EQ update:

    Settings/player EQ controls -> EstadoRadio
       -> update main EQ OR station EQ
       -> ServicioEcualizador.guardar(...)
       -> ServicioAudio applies if available

## File Changes

| File | Action | Description |
|---|---|---|
| `lib/servicios/servicio_ecualizador.dart` | Create | Load/save main EQ and station EQ map from SharedPreferences. |
| `lib/servicios/servicio_radio.dart` | Modify | Add injectable client/config, retry count, backoff, and host rotation. |
| `lib/estado/estado_radio.dart` | Modify | Inject services, load EQ during init, expose combined main listing, apply fallback EQ policy. |
| `lib/servicios/servicio_audio.dart` | Modify | Assign/clear `emisoraActual`; keep default behavior backward-compatible. |
| `lib/pantallas/pantalla_inicio.dart` | Modify | Use combined main listing when no genre filter. |
| `lib/pantallas/pantalla_ajustes.dart` | Modify | Distinguish main EQ from favorite-station own EQ controls. |
| `lib/modelos/preset_ecualizador.dart` | Modify | Add equality/copy helpers if tests need deterministic comparisons. |
| `test/servicios/servicio_radio_test.dart` | Create | Retry/host rotation tests. |
| `test/estado/estado_radio_test.dart` | Create | EQ persistence, custom listing, and station EQ policy tests. |
| `test/pantallas/pantalla_inicio_test.dart` | Create | Widget coverage for custom station rendering/favorite action. |

## Interfaces / Contracts

Suggested public surface:

```dart
class ServicioEcualizador {
  Future<ConfiguracionEcualizador> cargar();
  Future<void> guardarPrincipal(PresetEcualizador preset);
  Future<void> guardarPorEmisora(String uuid, PresetEcualizador preset);
  Future<void> eliminarPorEmisora(String uuid);
}
```

`ConfiguracionEcualizador` contains `PresetEcualizador principal` and `Map<String, PresetEcualizador> porEmisora`.

## Testing Strategy

| Layer | What to Test | Approach |
|---|---|---|
| Unit | `ServicioRadio` retries and rotates hosts | Fake `http.Client`, zero delay. |
| Unit | EQ load/save and fallback selection | SharedPreferences mock values + fake audio service. |
| Unit | Custom station added appears in combined listing | Inject fake custom storage or initial state. |
| Widget | Home renders custom station and favorite tap persists | Pump `PantallaInicio` with test `EstadoRadio`. |
| Regression | Current station updates for mini player/station EQ | Fake audio handler/service assertions. |

## Migration / Rollout

No destructive migration. On first run without EQ keys, use `PresetEcualizador.flat` as main EQ and empty per-station map. Existing export/import keys can be read opportunistically but app-local persistence should use the new service.

## Open Questions

- None blocking. The first implementation can place station EQ controls in Settings for the currently playing favorite; a richer per-favorite management screen can be deferred.
