import 'dart:async';

import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
import 'package:provider/provider.dart';

import '../estado/estado_alarmas.dart';
import '../estado/estado_radio.dart';
import '../modelos/alarma_musical.dart';
import '../servicios/servicio_audio.dart';
import '../widgets/pluri_glass_surface.dart';

class PantallaAlarmaSonando extends StatefulWidget {
  const PantallaAlarmaSonando({super.key, required this.alarma});

  final AlarmaMusical alarma;

  @override
  State<PantallaAlarmaSonando> createState() => _PantallaAlarmaSonandoState();
}

class _PantallaAlarmaSonandoState extends State<PantallaAlarmaSonando> {
  final AudioPlayer _fallbackPlayer = AudioPlayer();
  StreamSubscription<EstadoReproduccion>? _estadoSub;
  Timer? _fallbackTimer;
  bool _fallbackActivo = false;
  bool _radioIntentada = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => _iniciarAlarma());
  }

  Future<void> _iniciarAlarma() async {
    final radio = context.read<EstadoRadio>();
    await _fallbackPlayer.setVolume(widget.alarma.volumen.clamp(0.0, 1.0));
    await _fallbackPlayer.setLoopMode(LoopMode.one);

    final emisora = widget.alarma.emisora;
    if (emisora == null) {
      await _iniciarFallback();
      return;
    }

    _radioIntentada = true;
    await radio.audio.setVolumen(widget.alarma.volumen.clamp(0.0, 1.0));
    unawaited(radio.reproducir(emisora));

    _estadoSub = radio.estadoStream.listen((estado) {
      if (estado == EstadoReproduccion.reproduciendo && mounted) {
        _fallbackTimer?.cancel();
      }
      if (estado == EstadoReproduccion.error && mounted) {
        _iniciarFallback();
      }
    });

    _fallbackTimer = Timer(const Duration(seconds: 12), () {
      if (mounted) _iniciarFallback();
    });
  }

  Future<void> _iniciarFallback() async {
    if (_fallbackActivo) return;
    _fallbackActivo = true;
    await _fallbackPlayer.setAsset(_assetFallback(widget.alarma.sonidoInterno));
    await _fallbackPlayer.play();
    if (mounted) setState(() {});
  }

  Future<void> _detener() async {
    final radio = context.read<EstadoRadio>();
    final alarmas = context.read<EstadoAlarmas>();
    final navigator = Navigator.of(context);
    _fallbackTimer?.cancel();
    await _estadoSub?.cancel();
    await _fallbackPlayer.stop();
    await radio.audio.pausar();
    await alarmas.finalizarEjecucion(widget.alarma.id);
    if (mounted) navigator.pop();
  }

  Future<void> _posponer(int minutos) async {
    final radio = context.read<EstadoRadio>();
    final alarmas = context.read<EstadoAlarmas>();
    final navigator = Navigator.of(context);
    _fallbackTimer?.cancel();
    await _estadoSub?.cancel();
    await _fallbackPlayer.stop();
    await radio.audio.pausar();
    await alarmas.posponerAlarma(widget.alarma, minutos);
    if (mounted) navigator.pop();
  }

  @override
  void dispose() {
    _fallbackTimer?.cancel();
    _estadoSub?.cancel();
    _fallbackPlayer.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final alarma = widget.alarma;
    return Scaffold(
      backgroundColor: const Color(0xFF061722),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(20),
          child: Center(
            child: PluriGlassSurface(
              borderRadius: BorderRadius.circular(32),
              padding: const EdgeInsets.all(24),
              glowColor: const Color(0xFFFFB86B).withValues(alpha: 0.35),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Image.asset(
                    'assets/icons/alarmas/alarm_music.png',
                    width: 128,
                    height: 128,
                  ),
                  const SizedBox(height: 16),
                  Text(
                    _hora(alarma),
                    style: Theme.of(context).textTheme.displayMedium?.copyWith(
                      fontWeight: FontWeight.w900,
                      letterSpacing: -2,
                    ),
                  ),
                  const SizedBox(height: 8),
                  Text(
                    alarma.nombre,
                    textAlign: TextAlign.center,
                    style: Theme.of(context).textTheme.titleLarge,
                  ),
                  const SizedBox(height: 8),
                  Text(
                    _fallbackActivo
                        ? 'Sonando con audio seguro interno.'
                        : _radioIntentada
                        ? 'Intentando reproducir tu emisora con máxima calidad disponible.'
                        : 'Preparando audio seguro interno.',
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 22),
                  FilledButton.icon(
                    onPressed: _detener,
                    icon: const Icon(Icons.stop_rounded),
                    label: const Text('Detener alarma'),
                  ),
                  const SizedBox(height: 12),
                  Wrap(
                    spacing: 8,
                    children: [
                      for (final min in const [3, 5, 10])
                        ActionChip(
                          avatar: const Icon(Icons.snooze_rounded, size: 18),
                          label: Text('Posponer $min min'),
                          onPressed: () => _posponer(min),
                        ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

String _assetFallback(SonidoInternoAlarma sonido) => switch (sonido) {
      SonidoInternoAlarma.amanecer => 'assets/audio/alarm_amanecer.wav',
      SonidoInternoAlarma.campanaSuave =>
        'assets/audio/alarm_campana_suave.wav',
      SonidoInternoAlarma.pulsoDigital => 'assets/audio/alarm_pulso_digital.wav',
    };

String _hora(AlarmaMusical alarma) =>
    '${alarma.hora.toString().padLeft(2, '0')}:${alarma.minuto.toString().padLeft(2, '0')}';
