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/boloes_repository.dart';
import 'package:bolao_mobile/features/boloes/presentation/bolao_page.dart';
import 'package:bolao_mobile/features/boloes/presentation/rodada_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';

/// A aba de palpites carrega ao montar; sem este falso o teste faria HTTP real.
class _RepoFalso extends BoloesRepository {
  _RepoFalso() : super(ApiClient(SessaoStore()));

  @override
  Future<Rodada> rodada(String poolId, int matchday) async =>
      Rodada(serverTime: DateTime(2026, 8, 6, 12), jogos: const []);
}

Widget _app({required bool souAdmin, bool encerrado = false}) => ProviderScope(
  overrides: [boloesRepositoryProvider.overrideWithValue(_RepoFalso())],
  child: MaterialApp(
    home: BolaoPage(
      poolId: 'p1',
      nome: 'Bolão do setor',
      matchday: 20,
      souAdmin: souAdmin,
      encerrado: encerrado,
    ),
  ),
);

void main() {
  group('BolaoPage', () {
    testWidgets('a ação de convidar aparece para o admin', (t) async {
      await t.pumpWidget(_app(souAdmin: true));
      await t.pumpAndSettle();

      expect(find.byIcon(Icons.person_add_alt), findsOneWidget);
    });

    testWidgets('participante comum não vê a ação de convidar', (t) async {
      await t.pumpWidget(_app(souAdmin: false));
      await t.pumpAndSettle();

      // A autorização é do servidor (403), mas a UI não deve mentir sobre o
      // que a pessoa pode fazer — botão que sempre falha é pior que ausência.
      expect(find.byIcon(Icons.person_add_alt), findsNothing);
    });

    testWidgets('as três abas do bolão estão disponíveis', (t) async {
      await t.pumpWidget(_app(souAdmin: true));
      await t.pumpAndSettle();

      expect(find.text('Palpites'), findsOneWidget);
      expect(find.text('Ranking'), findsOneWidget);
      expect(find.text('Extrato'), findsOneWidget);
    });
  });

  group('CC-6-11 regras a um toque de qualquer aba', () {
    testWidgets('o menu do bolão leva às regras sem sair do fluxo', (t) async {
      await t.pumpWidget(_app(souAdmin: false));
      await t.pumpAndSettle();

      // Regra é consulta no meio da discussão: se custar navegação, ninguém
      // consulta e o admin volta a ser o árbitro.
      await t.tap(find.byType(PopupMenuButton<String>));
      await t.pumpAndSettle();

      expect(find.text('Regras do bolão'), findsOneWidget);
      expect(find.text('Avisos'), findsOneWidget);
      // Participante comum não recebe encerrar: o servidor recusaria com 403.
      expect(find.text('Encerrar o bolão'), findsNothing);
    });
  });

  group('CV-1 resultado alcançável depois de encerrar', () {
    testWidgets('bolão encerrado oferece campeão e classificação a todos', (
      t,
    ) async {
      await t.pumpWidget(_app(souAdmin: false, encerrado: true));
      await t.pumpAndSettle();
      await t.tap(find.byType(PopupMenuButton<String>));
      await t.pumpAndSettle();

      // Sem esta entrada, o campeão era visto **só** no instante em que o admin
      // encerrava — e o participante comum nunca o via.
      expect(find.text('Campeão e classificação final'), findsOneWidget);
      // E não se oferece encerrar o que já encerrou.
      expect(find.text('Encerrar o bolão'), findsNothing);
    });

    testWidgets('bolão em andamento não oferece resultado final', (t) async {
      await t.pumpWidget(_app(souAdmin: true));
      await t.pumpAndSettle();
      await t.tap(find.byType(PopupMenuButton<String>));
      await t.pumpAndSettle();

      expect(find.text('Campeão e classificação final'), findsNothing);
      expect(find.text('Encerrar o bolão'), findsOneWidget);
    });
  });
}
