import 'package:bolao_mobile/core/api/api_client.dart';
import 'package:bolao_mobile/core/tema/tema.dart';
import 'package:bolao_mobile/core/sessao/sessao_store.dart';
import 'package:bolao_mobile/features/boloes/data/ranking_repository.dart';
import 'package:bolao_mobile/features/boloes/presentation/ranking_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';

class _RepoFalso extends RankingRepository {
  _RepoFalso(this.resposta) : super(ApiClient(SessaoStore()));

  final Extrato resposta;

  @override
  Future<Extrato> extrato(String poolId, int matchday) async => resposta;
}

LinhaExtrato _linha({
  required String casa,
  required String fora,
  required String estado,
  int? pontos,
  String? band,
  int? palpiteCasa,
  int? palpiteFora,
  int? oficialCasa,
  int? oficialFora,
}) => LinhaExtrato(
  homeTeam: casa,
  awayTeam: fora,
  estado: estado,
  points: pontos,
  band: band,
  palpiteCasa: palpiteCasa,
  palpiteFora: palpiteFora,
  oficialCasa: oficialCasa,
  oficialFora: oficialFora,
);

Widget _app(Extrato extrato) => ProviderScope(
  overrides: [rankingRepositoryProvider.overrideWithValue(_RepoFalso(extrato))],
  // A tela vive dentro do Scaffold de BolaoPage (as abas), e é ele que
  // fornece o Material que o ListTile exige.
  child: MaterialApp(
    // Com o tema do app: o banner de total usa cor de par do esquema, e sem o
    // tema o teste mediria o esquema padrão do Flutter.
    theme: temaDoApp(),
    home: const Scaffold(body: ExtratoPage(poolId: 'p1', matchday: 20)),
  ),
);

void main() {
  group('ExtratoPage', () {
    testWidgets('mostra a conta do ponto: palpite, oficial e motivo', (
      t,
    ) async {
      await t.pumpWidget(
        _app(
          Extrato(
            total: 10,
            linhas: [
              _linha(
                casa: 'Corinthians',
                fora: 'Bahia',
                estado: 'APURADO',
                pontos: 10,
                band: 'PLACAR_EXATO',
                palpiteCasa: 2,
                palpiteFora: 1,
                oficialCasa: 2,
                oficialFora: 1,
              ),
            ],
          ),
        ),
      );
      await t.pumpAndSettle();

      // É o que dispensa "confia" como resposta do organizador.
      expect(find.text('Seu palpite: 2x1  ·  Oficial: 2x1'), findsOneWidget);
      expect(find.text('placar exato'), findsOneWidget);
      expect(find.text('10 pts'), findsOneWidget);
      expect(find.textContaining('Total da rodada 20: 10'), findsOneWidget);
    });

    testWidgets('o total da rodada é legível sobre a cor da marca', (t) async {
      // Regressão de 07/08: `primaryContainer` passou a ser a cor cheia da marca
      // (#615FF6) com a identidade nova, e o banner usava o texto escuro padrão —
      // contraste 3.64, abaixo do mínimo de 4.5. O par correto dá 4.54.
      await t.pumpWidget(
        _app(
          const Extrato(
            total: 7,
            linhas: [
              LinhaExtrato(
                homeTeam: 'Vasco',
                awayTeam: 'Santos',
                estado: 'APURADO',
                points: 7,
                band: 'SO_VENCEDOR',
                palpiteCasa: 1,
                palpiteFora: 0,
                oficialCasa: 2,
                oficialFora: 1,
              ),
            ],
          ),
        ),
      );
      await t.pumpAndSettle();

      final banner = t.widget<Text>(
        find.textContaining('Total da rodada 20: 7'),
      );
      final cores = temaDoApp().colorScheme;
      expect(banner.style?.color, cores.onPrimaryContainer);
      expect(banner.style?.color, isNot(cores.onSurface));
    });

    testWidgets('jogo terminado sem palpite diz que faltou o palpite', (
      t,
    ) async {
      await t.pumpWidget(
        _app(
          Extrato(
            total: 0,
            linhas: [
              _linha(
                casa: 'Internacional',
                fora: 'Bragantino',
                estado: 'SEM_PALPITE',
                pontos: 0,
                oficialCasa: 1,
                oficialFora: 0,
              ),
            ],
          ),
        ),
      );
      await t.pumpAndSettle();

      // O resultado chegou; o palpite é que faltou. "Aguardando resultado"
      // aqui seria falso e esconderia o esquecimento do participante.
      expect(find.text('você não palpitou neste jogo'), findsOneWidget);
      expect(find.text('aguardando resultado'), findsNothing);
      expect(find.text('0 pts'), findsOneWidget);
    });

    testWidgets('placar atrasado continua como espera, não como zero', (
      t,
    ) async {
      await t.pumpWidget(
        _app(
          Extrato(
            total: 0,
            linhas: [
              _linha(
                casa: 'Fluminense',
                fora: 'Vitória',
                estado: 'AGUARDANDO_RESULTADO',
                palpiteCasa: 1,
                palpiteFora: 1,
              ),
            ],
          ),
        ),
      );
      await t.pumpAndSettle();

      // O tier gratuito atrasa o placar: mostrar 0 aqui seria acusar o
      // participante de errar um jogo que ninguém apurou ainda.
      expect(find.text('aguardando resultado'), findsOneWidget);
      expect(find.text('—'), findsOneWidget);
    });

    testWidgets('prazo aberto é sinalizado como chance de palpitar', (t) async {
      await t.pumpWidget(
        _app(
          Extrato(
            total: 0,
            linhas: [
              _linha(casa: 'Santos', fora: 'Cuiabá', estado: 'PRAZO_ABERTO'),
            ],
          ),
        ),
      );
      await t.pumpAndSettle();

      expect(find.text('prazo ainda aberto'), findsOneWidget);
    });
  });
}
