import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import '../servicios/servicio_audio.dart';

/// Visualizador de audio animado para la pantalla del reproductor.
///
/// Muestra barras verticales que se animan con movimiento pseudo-aleatorio
/// basado en ruido suavizado mientras la radio está reproduciéndose.
/// Cuando está pausado/detenido, las barras se aplanan suavemente.
///
/// ### Implementación
/// No usa FFT real (requeriría captura de micrófono con permisos).
/// En cambio, usa un generador de movimiento orgánico con interpolación
/// suavizada — el resultado visual es similar al de apps de streaming como
/// Spotify o Apple Music en sus visualizadores de "en reproducción".
///
/// ### Uso
/// ```dart
/// VisualizadorAudio(
///   estadoStream: estado.estadoStream,
///   barras: 24,
///   color: theme.colorScheme.primary,
///   altura: 60,
/// )
/// ```
class VisualizadorAudio extends StatefulWidget {
  final Stream<EstadoReproduccion> estadoStream;
  final int barras;
  final Color? color;
  final double altura;
  final double anchuraTotal;

  const VisualizadorAudio({
    super.key,
    required this.estadoStream,
    this.barras = 20,
    this.color,
    this.altura = 48,
    this.anchuraTotal = double.infinity,
  });

  @override
  State<VisualizadorAudio> createState() => _VisualizadorAudioState();
}

class _VisualizadorAudioState extends State<VisualizadorAudio>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  bool _activo = false;
  StreamSubscription<EstadoReproduccion>? _estadoSubscription;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 2),
    )..addListener(() {
        if (mounted) setState(() {});
      });
    _estadoSubscription = widget.estadoStream.listen(_onEstado);
  }

  void _onEstado(EstadoReproduccion estado) {
    final nuevoActivo = estado == EstadoReproduccion.reproduciendo ||
        estado == EstadoReproduccion.cargando;
    if (nuevoActivo == _activo) return;
    if (!mounted) return;
    setState(() => _activo = nuevoActivo);
    nuevoActivo ? _controller.repeat() : _controller.stop();
  }

  @override
  void dispose() {
    _estadoSubscription?.cancel();
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final color = widget.color ?? Theme.of(context).colorScheme.primary;
    final t = _controller.value * pi * 2;
    return SizedBox(
      height: widget.altura,
      child: RepaintBoundary(
        child: CustomPaint(
          painter: _WaveFlowPainter(
            color: color,
            phase: t,
            active: _activo,
          ),
          child: const SizedBox.expand(),
        ),
      ),
    );
  }
}

class _WaveFlowPainter extends CustomPainter {
  const _WaveFlowPainter({
    required this.color,
    required this.phase,
    required this.active,
  });

  final Color color;
  final double phase;
  final bool active;

  @override
  void paint(Canvas canvas, Size size) {
    final center = size.height / 2;
    final amp = active ? size.height * 0.24 : size.height * 0.06;
    final glowPaint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = active ? 8 : 4
      ..strokeCap = StrokeCap.round
      ..color = color.withValues(alpha: active ? 0.18 : 0.08);
    final linePaint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3
      ..strokeCap = StrokeCap.round
      ..shader = LinearGradient(
        colors: [
          color.withValues(alpha: 0.08),
          color.withValues(alpha: active ? 0.95 : 0.35),
          const Color(0xFFF4B860).withValues(alpha: active ? 0.75 : 0.20),
          color.withValues(alpha: 0.08),
        ],
      ).createShader(Offset.zero & size);

    Path pathFor(double shift, double amplitude) {
      final path = Path()..moveTo(0, center);
      for (double x = 0; x <= size.width; x += 8) {
        final p = x / size.width;
        final y = center +
            sin((p * pi * 2.4) + phase + shift) * amplitude +
            sin((p * pi * 5.2) - phase * 0.7 + shift) * amplitude * 0.32;
        path.lineTo(x, y);
      }
      return path;
    }

    canvas.drawPath(pathFor(0, amp), glowPaint);
    canvas.drawPath(pathFor(0.6, amp * 0.62), glowPaint..color = color.withValues(alpha: active ? 0.10 : 0.05));
    canvas.drawPath(pathFor(0, amp), linePaint);
    canvas.drawPath(
      pathFor(0.9, amp * 0.58),
      Paint()
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2
        ..strokeCap = StrokeCap.round
        ..color = Colors.white.withValues(alpha: active ? 0.35 : 0.12),
    );
  }

  @override
  bool shouldRepaint(covariant _WaveFlowPainter oldDelegate) {
    return oldDelegate.phase != phase ||
        oldDelegate.active != active ||
        oldDelegate.color != color;
  }
}

/// Versión compacta del visualizador — 5 barras, para uso en MiniReproductor
/// o indicadores pequeños de "en reproducción".
class IndicadorReproduccion extends StatefulWidget {
  final Stream<EstadoReproduccion> estadoStream;
  final Color? color;
  final double size;

  const IndicadorReproduccion({
    super.key,
    required this.estadoStream,
    this.color,
    this.size = 16,
  });

  @override
  State<IndicadorReproduccion> createState() => _IndicadorReproduccionState();
}

class _IndicadorReproduccionState extends State<IndicadorReproduccion>
    with SingleTickerProviderStateMixin {
  late AnimationController _ctrl;
  bool _reproduciendo = false;
  StreamSubscription<EstadoReproduccion>? _estadoSubscription;

  @override
  void initState() {
    super.initState();
    _ctrl = AnimationController(vsync: this, duration: const Duration(milliseconds: 600))
      ..addListener(() => setState(() {}));
    _estadoSubscription = widget.estadoStream.listen((s) {
      final rep = s == EstadoReproduccion.reproduciendo;
      if (rep == _reproduciendo) return;
      if (!mounted) return;
      setState(() => _reproduciendo = rep);
      rep ? _ctrl.repeat(reverse: true) : _ctrl.stop();
    });
  }

  @override
  void dispose() {
    _estadoSubscription?.cancel();
    _ctrl.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final color = widget.color ??
        Theme.of(context).colorScheme.primary;
    if (!_reproduciendo) {
      return Icon(Icons.radio, size: widget.size,
          color: Theme.of(context).colorScheme.onSurfaceVariant);
    }
    return Row(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.end,
      children: List.generate(3, (i) {
        final alts = [0.5, 1.0, 0.7];
        final fases = [0.0, 0.3, 0.6];
        final h = ((sin(_ctrl.value * pi + fases[i]) + 1) / 2 * alts[i] + 0.2)
            .clamp(0.15, 1.0) * widget.size;
        return Container(
          width: widget.size * 0.2,
          height: h,
          margin: EdgeInsets.only(right: i < 2 ? widget.size * 0.1 : 0),
          decoration: BoxDecoration(
            color: color,
            borderRadius: BorderRadius.circular(1),
          ),
        );
      }),
    );
  }
}
