import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pluriwave/estado/estado_radio.dart';
import 'package:pluriwave/pantallas/pantalla_favoritos.dart';
import 'package:pluriwave/pantallas/pantalla_inicio.dart';
import 'package:provider/provider.dart';

import '../helpers/fakes.dart';

void main() {
  testWidgets(
      'PantallaInicio muestra custom, reproducir usa EstadoRadio y favorito usa flujo existente',
      (tester) async {
    final audio = FakeServicioAudio();
    final favoritos = FakeServicioFavoritos();
    final radio = FakeServicioRadio();
    final custom = emisoraDemo(uuid: 'custom-1', nombre: 'Custom Uno');
    final archivo = await _crearArchivoCustom([custom]);
    final estado = EstadoRadio(
      audio: audio,
      favoritos: favoritos,
      radio: radio,
      servicioEcualizador: FakeServicioEcualizador(),
      resolverArchivoCustom: () async => archivo,
      iniciarAutomaticamente: false,
    );
    await estado.inicializar();

    await tester.pumpWidget(
      ChangeNotifierProvider<EstadoRadio>.value(
        value: estado,
        child: const MaterialApp(
          home: Scaffold(body: PantallaInicio()),
        ),
      ),
    );
    await tester.pumpAndSettle();

    expect(find.text('Custom Uno'), findsOneWidget);

    await tester.tap(find.text('Custom Uno'));
    await tester.pumpAndSettle();
    expect(audio.emisorasReproducidas.map((e) => e.uuid), contains('custom-1'));
    expect(radio.ultimoUuidClick, 'custom-1');

    final tarjetaCustom = find.ancestor(
      of: find.text('Custom Uno'),
      matching: find.byType(Card),
    );
    final botonFavorito = find.descendant(
      of: tarjetaCustom.first,
      matching: find.byIcon(Icons.favorite_outline_rounded),
    );
    expect(botonFavorito, findsOneWidget);

    await tester.tap(botonFavorito);
    await tester.pumpAndSettle();

    expect(favoritos.toggleCalls, 1);
    expect(await favoritos.esFavorito(custom.uuid), isTrue);
  });

  testWidgets(
      'PantallaInicio permite reintentar manualmente tras fallo inicial agotado',
      (tester) async {
    final radio = FakeServicioRadio(
      erroresPopularesPorLlamada: [Exception('sin red')],
      popularesPorLlamada: [
        const [],
        [emisoraDemo(uuid: 'api-1', nombre: 'API Uno')],
      ],
      tendenciasPorLlamada: [
        const [],
        [emisoraDemo(uuid: 'trend-1', nombre: 'Trend Uno')],
      ],
    );
    final estado = EstadoRadio(
      audio: FakeServicioAudio(),
      favoritos: FakeServicioFavoritos(),
      radio: radio,
      servicioEcualizador: FakeServicioEcualizador(),
      resolverArchivoCustom: _archivoCustomVacio,
      iniciarAutomaticamente: false,
    );
    await estado.inicializar();

    await tester.pumpWidget(
      ChangeNotifierProvider<EstadoRadio>.value(
        value: estado,
        child: const MaterialApp(
          home: Scaffold(body: PantallaInicio()),
        ),
      ),
    );
    await tester.pumpAndSettle();

    expect(find.text('Sin conexión a la API de radio'), findsOneWidget);
    expect(find.text('Reintentar'), findsOneWidget);

    await tester.tap(find.text('Reintentar'));
    await tester.pumpAndSettle();

    expect(radio.obtenerPopularesCalls, 2);
    expect(find.text('Sin conexión a la API de radio'), findsNothing);
    expect(find.text('API Uno'), findsOneWidget);
  });

  testWidgets('PantallaFavoritos muestra custom favorito tras recarga',
      (tester) async {
    final favoritos = FakeServicioFavoritos();
    final custom = emisoraDemo(uuid: 'custom-1', nombre: 'Custom Uno');
    final archivo = await _crearArchivoCustom([custom]);
    final estado = EstadoRadio(
      audio: FakeServicioAudio(),
      favoritos: favoritos,
      radio: FakeServicioRadio(
        populares: [emisoraDemo(uuid: 'api-1', nombre: 'API Uno')],
      ),
      servicioEcualizador: FakeServicioEcualizador(),
      resolverArchivoCustom: () async => archivo,
      iniciarAutomaticamente: false,
    );
    await estado.inicializar();

    await tester.pumpWidget(
      ChangeNotifierProvider<EstadoRadio>.value(
        value: estado,
        child: const MaterialApp(
          home: Scaffold(body: PantallaInicio()),
        ),
      ),
    );
    await tester.pumpAndSettle();

    final tarjetaCustom = find.ancestor(
      of: find.text('Custom Uno'),
      matching: find.byType(Card),
    );
    final botonFavorito = find.descendant(
      of: tarjetaCustom.first,
      matching: find.byIcon(Icons.favorite_outline_rounded),
    );
    expect(botonFavorito, findsOneWidget);

    await tester.tap(botonFavorito);
    await tester.pumpAndSettle();

    await tester.pumpWidget(
      ChangeNotifierProvider<EstadoRadio>.value(
        value: estado,
        child: const MaterialApp(
          home: Scaffold(body: PantallaFavoritos()),
        ),
      ),
    );
    await tester.pumpAndSettle();

    expect(await favoritos.esFavorito(custom.uuid), isTrue);
    expect(find.text('Custom Uno'), findsOneWidget);
  });
}

Future<File> _crearArchivoCustom(List<dynamic> emisoras) async {
  final dir = await Directory.systemTemp.createTemp('pluriwave-test-');
  final archivo = File('${dir.path}/emisoras_custom.json');
  await archivo.writeAsString(jsonEncode(emisoras.map((e) => e.toMap()).toList()));
  return archivo;
}

Future<File> _archivoCustomVacio() async => _crearArchivoCustom(const []);
