import 'package:bolao_mobile/core/api/api_client.dart';
import 'package:bolao_mobile/core/sessao/sessao_store.dart';
import 'package:bolao_mobile/features/boloes/data/ciclo_vida_repository.dart';
import 'package:bolao_mobile/features/boloes/data/participantes_repository.dart';
import 'package:bolao_mobile/features/boloes/presentation/encerramento_dialog.dart';
import 'package:bolao_mobile/features/boloes/presentation/participantes_page.dart';
import 'package:bolao_mobile/features/boloes/presentation/recriar_temporada_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';

class _CicloFalso extends CicloVidaRepository {
  _CicloFalso({this.erro}) : super(ApiClient(SessaoStore()));

  final ApiError? erro;
  final List<({int de, int ate, String? nome})> chamadas = [];

  @override
  Future<({int herdados, String id, String nome, int totalJogos})> recriar(
    String poolId, {
    required int rodadaInicial,
    required int rodadaFinal,
    String? nome,
  }) async {
    if (erro != null) throw erro!;
    chamadas.add((de: rodadaInicial, ate: rodadaFinal, nome: nome));
    return (id: 'p2', nome: nome ?? 'Bolão', herdados: 7, totalJogos: 380);
  }
}

class _ParticipantesFalso extends ParticipantesRepository {
  _ParticipantesFalso() : super(ApiClient(SessaoStore()));

  @override
  Future<Regras> regras(String poolId) async => Regras(
    pontosExato: 20,
    pontosVencedorSaldo: 10,
    pontosVencedor: 5,
    ordemDesempate: const ['EXACT_SCORES', 'WINNERS'],
    travadas: true,
    proximoPrazo: null,
  );

  @override
  Future<ListaParticipantes> listar(String poolId) async => ListaParticipantes(
    total: 8,
    linhas: [
      for (var i = 0; i < 7; i++)
        Participante(
          userId: 'u$i',
          displayName: 'P$i',
          isAdmin: false,
          isCreator: i == 0,
          ativo: true,
        ),
      // Quem saiu não deve entrar na conta do que será herdado.
      const Participante(
        userId: 'u9',
        displayName: 'Saiu',
        isAdmin: false,
        isCreator: false,
        ativo: false,
      ),
    ],
  );
}

Widget _app(_CicloFalso ciclo, {String nome = 'Bolão do setor'}) =>
    ProviderScope(
      overrides: [
        cicloVidaRepositoryProvider.overrideWithValue(ciclo),
        participantesRepositoryProvider.overrideWithValue(
          _ParticipantesFalso(),
        ),
      ],
      child: MaterialApp(
        home: Scaffold(
          body: RecriarTemporadaDialog(poolId: 'p1', nomeAtual: nome),
        ),
      ),
    );

void main() {
  group('RecriarTemporadaDialog', () {
    testWidgets('CV-7 FE-2 mostra o que vem e o que NÃO vem', (t) async {
      await t.pumpWidget(_app(_CicloFalso()));
      await t.pumpAndSettle();

      // Herdar palpite ou ponto corromperia a competição nova: é o critério
      // mais importante da story, e tem que estar dito antes de confirmar.
      expect(find.text('· 7 participante(s), sem reconvidar'), findsOneWidget);
      expect(find.text('· a mesma pontuação: 20 / 10 / 5'), findsOneWidget);
      expect(
        find.textContaining('nenhum palpite e nenhum ponto'),
        findsOneWidget,
      );
    });

    testWidgets('a contagem herdada ignora quem saiu do bolão', (t) async {
      await t.pumpWidget(_app(_CicloFalso()));
      await t.pumpAndSettle();

      // 8 no total, 7 ativos: prometer 8 seria prometer gente que não volta.
      expect(find.textContaining('8 participante'), findsNothing);
    });

    testWidgets('o nome padrão é o do bolão anterior, sem inventar sufixo', (
      t,
    ) async {
      await t.pumpWidget(_app(_CicloFalso(), nome: 'Bolao 2026'));
      await t.pumpAndSettle();

      // Anexar ano cegamente produzia "Bolao 2026 2027".
      final campos = t.widgetList<TextField>(find.byType(TextField)).toList();
      expect(campos.first.controller?.text, 'Bolao 2026');
    });

    testWidgets('recria com as rodadas informadas e confirma o resultado', (
      t,
    ) async {
      final ciclo = _CicloFalso();
      await t.pumpWidget(_app(ciclo));
      await t.pumpAndSettle();

      await t.tap(find.text('Criar temporada nova'));
      await t.pumpAndSettle();

      expect(ciclo.chamadas.single.de, 1);
      expect(ciclo.chamadas.single.ate, 38);
      expect(
        find.textContaining('7 participante(s) já estão dentro'),
        findsOneWidget,
      );
      expect(find.textContaining('começa em zero'), findsOneWidget);
    });

    testWidgets('rodada inválida é barrada antes do servidor', (t) async {
      final ciclo = _CicloFalso();
      await t.pumpWidget(_app(ciclo));
      await t.pumpAndSettle();

      // Final antes da inicial.
      final campos = find.byType(TextField);
      await t.enterText(campos.at(1), '30');
      await t.enterText(campos.at(2), '10');
      await t.tap(find.text('Criar temporada nova'));
      await t.pumpAndSettle();

      expect(ciclo.chamadas, isEmpty);
      expect(find.textContaining('rodadas entre 1 e 38'), findsOneWidget);
    });

    testWidgets('recusa do servidor aparece com o motivo', (t) async {
      final ciclo = _CicloFalso(
        erro: ApiError('este bolão ainda está em andamento', status: 409),
      );
      await t.pumpWidget(_app(ciclo));
      await t.pumpAndSettle();

      await t.tap(find.text('Criar temporada nova'));
      await t.pumpAndSettle();

      expect(find.text('este bolão ainda está em andamento'), findsOneWidget);
    });
  });
}
