import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'estado/estado_radio.dart';
import 'estado/estado_alarmas.dart';
import 'modelos/alarma_musical.dart';
import 'pantallas/pantalla_alarmas.dart';
import 'pantallas/pantalla_alarma_sonando.dart';
import 'pantallas/pantalla_inicio.dart';
import 'pantallas/pantalla_buscar.dart';
import 'pantallas/pantalla_favoritos.dart';
import 'pantallas/pantalla_ajustes.dart';
import 'tema/pluriwave_theme.dart';
import 'widgets/pluri_bottom_navigation.dart';
import 'widgets/pluri_icon.dart';
import 'widgets/pluri_layout.dart';
import 'widgets/pluri_wave_scaffold.dart';
import 'package:pluriwave/widgets/mini_reproductor.dart';
import 'servicios/servicio_alarmas_android.dart';

class PluriWaveApp extends StatelessWidget {
  const PluriWaveApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => EstadoRadio()),
        ChangeNotifierProvider(create: (_) => EstadoAlarmas()),
      ],
      child: MaterialApp(
        title: 'PluriWave',
        debugShowCheckedModeBanner: false,
        theme: PluriWaveTheme.dark(),
        darkTheme: PluriWaveTheme.dark(),
        themeMode: ThemeMode.dark,
        home: const _PaginaPrincipal(),
      ),
    );
  }
}

class _PaginaPrincipal extends StatefulWidget {
  const _PaginaPrincipal();

  @override
  State<_PaginaPrincipal> createState() => _PaginaPrincipalState();
}

class _PaginaPrincipalState extends State<_PaginaPrincipal> {
  int _indice = 0;
  StreamSubscription<String>? _errorSubscription;
  StreamSubscription<EventoAlarmaAndroid>? _alarmaSubscription;
  StreamSubscription<AlarmaMusical>? _alarmaVencidaSubscription;
  EstadoRadio? _estadoSuscrito;
  bool _alarmaInicialProcesada = false;

  static const _paginas = [
    PantallaInicio(),
    PantallaBuscar(),
    PantallaFavoritos(),
    PantallaAlarmas(),
    PantallaAjustes(),
  ];

  static const _navItems = [
    PluriNavItem(
      glyph: PluriIconGlyph.home,
      label: 'Inicio',
    ),
    PluriNavItem(
      glyph: PluriIconGlyph.search,
      label: 'Buscar',
    ),
    PluriNavItem(
      glyph: PluriIconGlyph.favorites,
      label: 'Favoritos',
    ),
    PluriNavItem(
      glyph: PluriIconGlyph.alarm,
      label: 'Alarmas',
    ),
    PluriNavItem(
      glyph: PluriIconGlyph.settings,
      label: 'Ajustes',
    ),
  ];

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final estado = context.read<EstadoRadio>();
    if (identical(_estadoSuscrito, estado) && _errorSubscription != null) {
      return;
    }
    _errorSubscription?.cancel();
    _estadoSuscrito = estado;
    _errorSubscription = estado.errorStream.listen((msg) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(msg),
          duration: const Duration(seconds: 3),
          action: SnackBarAction(label: 'OK', onPressed: () {}),
        ),
      );
    });

    final alarmas = context.read<EstadoAlarmas>();
    _alarmaSubscription ??= alarmas.android.eventosAlarma.listen((evento) {
      if (!mounted) return;
      _abrirAlarmaSonando(evento);
    });
    _alarmaVencidaSubscription ??= alarmas.alarmasVencidasStream.listen((
      alarma,
    ) {
      if (!mounted) return;
      _abrirAlarmaDirecta(alarma);
    });
    if (!_alarmaInicialProcesada) {
      _alarmaInicialProcesada = true;
      unawaited(_procesarAlarmaInicial(alarmas));
    }
  }

  @override
  void dispose() {
    _errorSubscription?.cancel();
    _alarmaSubscription?.cancel();
    _alarmaVencidaSubscription?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return PluriWaveScaffold(
      appBar: AppBar(
        title: const Text('PluriWave'),
        actions: [
          IconButton(
            icon: const Icon(Icons.bedtime_outlined),
            tooltip: 'Timer de sueño',
            onPressed: () => _mostrarTimerDialog(context),
          ),
        ],
      ),
      body: SafeArea(
        top: false,
        child: AnimatedSwitcher(
          duration: context.pluriMotion.normal,
          switchInCurve: Curves.easeOutCubic,
          switchOutCurve: Curves.easeInCubic,
          transitionBuilder:
              (child, animation) => FadeTransition(
                opacity: animation,
                child: SlideTransition(
                  position: Tween<Offset>(
                    begin: const Offset(0.035, 0),
                    end: Offset.zero,
                  ).animate(animation),
                  child: child,
                ),
              ),
          child: KeyedSubtree(
            key: ValueKey<int>(_indice),
            child: _paginas[_indice],
          ),
        ),
      ),
      bottomNavigationBar: SafeArea(
        top: false,
        minimum: const EdgeInsets.only(bottom: PluriLayout.compactGap),
        child: Padding(
          padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              const MiniReproductor(),
              PluriBottomNavigation(
                items: _navItems,
                selectedIndex: _indice,
                onSelected: (i) => setState(() => _indice = i),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> _procesarAlarmaInicial(EstadoAlarmas alarmas) async {
    final evento = await alarmas.android.obtenerEventoInicial();
    if (evento != null && mounted) {
      await _abrirAlarmaSonando(evento);
    }
  }

  Future<void> _abrirAlarmaSonando(EventoAlarmaAndroid evento) async {
    final estado = context.read<EstadoAlarmas>();
    await estado.refrescarProgramacion();
    AlarmaMusical? alarma;
    for (final item in estado.alarmas) {
      if (item.id == evento.alarmaId) {
        alarma = item;
        break;
      }
    }
    if (alarma == null || !mounted) return;
    if (evento.accion.endsWith('.SKIP_NEXT')) {
      await estado.saltarProxima(alarma.id);
      if (!mounted) return;
      setState(() => _indice = 3);
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('Omitida esta ejecución de ${alarma.nombre}.'),
        ),
      );
      return;
    }
    if (evento.accion.endsWith('.PRE_NOTICE')) {
      setState(() => _indice = 3);
      return;
    }
    await Navigator.of(context).push(
      MaterialPageRoute<void>(
        builder: (_) => PantallaAlarmaSonando(alarma: alarma!),
        fullscreenDialog: true,
      ),
    );
  }

  Future<void> _abrirAlarmaDirecta(AlarmaMusical alarma) async {
    await Navigator.of(context).push(
      MaterialPageRoute<void>(
        builder: (_) => PantallaAlarmaSonando(alarma: alarma),
        fullscreenDialog: true,
      ),
    );
  }

  void _mostrarTimerDialog(BuildContext context) {
    showModalBottomSheet(
      context: context,
      showDragHandle: true,
      builder:
          (ctx) => Consumer<EstadoRadio>(
            builder: (ctx, estado, _) => SafeArea(
              child: Padding(
                padding: PluriLayout.sheetPadding,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Timer de sueño',
                      style: Theme.of(ctx).textTheme.titleLarge,
                    ),
                    const SizedBox(height: PluriLayout.sectionGap),
                    Text(
                      'Apagado suave de la radio con cuenta atrás exacta.',
                      style: Theme.of(ctx).textTheme.bodySmall,
                    ),
                    const SizedBox(height: PluriLayout.panelGap),
                    if (estado.timer.activo)
                      StreamBuilder<Duration>(
                        stream: estado.timer.tiempoRestanteStream,
                        builder: (ctx, snap) {
                          final restante =
                              snap.data ?? estado.timer.tiempoRestante;
                          return Column(
                            crossAxisAlignment: CrossAxisAlignment.stretch,
                            children: [
                              Text(
                                _formatearDuracionTimer(restante),
                                style: Theme.of(ctx).textTheme.headlineMedium,
                              ),
                              const SizedBox(height: PluriLayout.compactGap),
                              FilledButton.tonal(
                                onPressed: () {
                                  estado.cancelarTimer();
                                  Navigator.pop(ctx);
                                },
                                child: const Text('Cancelar timer'),
                              ),
                            ],
                          );
                        },
                      )
                    else
                      Wrap(
                        spacing: PluriLayout.compactGap,
                        runSpacing: PluriLayout.compactGap,
                        children: [
                          for (final segundos
                              in estado.timerSuenoPresetsSegundos)
                            ActionChip(
                              label: Text(
                                _formatearDuracionTimer(
                                  Duration(seconds: segundos),
                                ),
                              ),
                              onPressed: () {
                                estado.iniciarTimerDuracion(
                                  Duration(seconds: segundos),
                                );
                                Navigator.pop(ctx);
                              },
                            ),
                          ActionChip(
                            avatar: const Icon(Icons.tune_rounded, size: 18),
                            label: const Text('Otro'),
                            onPressed: () async {
                              final duracion =
                                  await _pedirDuracionPersonalizada(ctx);
                              if (duracion == null || !ctx.mounted) return;
                              estado.iniciarTimerDuracion(duracion);
                              Navigator.pop(ctx);
                            },
                          ),
                        ],
                      ),
                  ],
                ),
              ),
            ),
          ),
    );
  }

  Future<Duration?> _pedirDuracionPersonalizada(BuildContext context) {
    return showModalBottomSheet<Duration>(
      context: context,
      isScrollControlled: true,
      showDragHandle: true,
      builder: (ctx) => const _TimerPersonalizadoSheet(),
    );
  }
}

String _formatearDuracionTimer(Duration duracion) {
  final horas = duracion.inHours;
  final minutos = duracion.inMinutes.remainder(60);
  final segundos = duracion.inSeconds.remainder(60);
  if (horas > 0) {
    return '${horas}h ${minutos.toString().padLeft(2, '0')}m ${segundos.toString().padLeft(2, '0')}s';
  }
  if (minutos > 0) {
    return segundos == 0 ? '$minutos min' : '${minutos}m ${segundos}s';
  }
  return '$segundos s';
}

class _TimerPersonalizadoSheet extends StatefulWidget {
  const _TimerPersonalizadoSheet();

  @override
  State<_TimerPersonalizadoSheet> createState() =>
      _TimerPersonalizadoSheetState();
}

class _TimerPersonalizadoSheetState extends State<_TimerPersonalizadoSheet> {
  final _horasCtrl = TextEditingController();
  final _minutosCtrl = TextEditingController(text: '15');
  final _segundosCtrl = TextEditingController();
  bool _guardarPreset = true;

  @override
  void dispose() {
    _horasCtrl.dispose();
    _minutosCtrl.dispose();
    _segundosCtrl.dispose();
    super.dispose();
  }

  int _leer(TextEditingController ctrl) => int.tryParse(ctrl.text.trim()) ?? 0;

  Future<void> _confirmar() async {
    final duracion = Duration(
      hours: _leer(_horasCtrl),
      minutes: _leer(_minutosCtrl),
      seconds: _leer(_segundosCtrl),
    );
    if (duracion <= Duration.zero) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Elegí una duración mayor que cero.')),
      );
      return;
    }
    if (_guardarPreset) {
      await context.read<EstadoRadio>().agregarTimerSuenoPreset(duracion);
    }
    if (mounted) Navigator.pop(context, duracion);
  }

  @override
  Widget build(BuildContext context) {
    final bottom = MediaQuery.viewInsetsOf(context).bottom;
    return SafeArea(
      child: Padding(
        padding: EdgeInsets.fromLTRB(18, 0, 18, 18 + bottom),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              'Duración personalizada',
              style: Theme.of(context).textTheme.titleLarge,
            ),
            const SizedBox(height: PluriLayout.sectionGap),
            Row(
              children: [
                Expanded(child: _campoTiempo(_horasCtrl, 'Horas')),
                const SizedBox(width: PluriLayout.compactGap),
                Expanded(child: _campoTiempo(_minutosCtrl, 'Minutos')),
                const SizedBox(width: PluriLayout.compactGap),
                Expanded(child: _campoTiempo(_segundosCtrl, 'Segundos')),
              ],
            ),
            const SizedBox(height: PluriLayout.compactGap),
            SwitchListTile.adaptive(
              contentPadding: EdgeInsets.zero,
              title: const Text('Guardar como acceso rápido'),
              value: _guardarPreset,
              onChanged: (value) => setState(() => _guardarPreset = value),
            ),
            const SizedBox(height: PluriLayout.sectionGap),
            FilledButton.icon(
              icon: const Icon(Icons.bedtime_rounded),
              label: const Text('Iniciar timer'),
              onPressed: _confirmar,
            ),
          ],
        ),
      ),
    );
  }

  Widget _campoTiempo(TextEditingController controller, String label) {
    return TextField(
      controller: controller,
      keyboardType: TextInputType.number,
      decoration: InputDecoration(
        labelText: label,
        border: const OutlineInputBorder(),
      ),
    );
  }
}
