import 'package:cloud_firestore/cloud_firestore.dart';

import '../../../core/firebase/chamadas.dart';
import 'ranking_repository.dart';

/// Ranking e extrato sobre Firestore.
///
/// O ranking geral é **uma consulta** na classificação materializada, do
/// tamanho da página — não do tamanho do bolão. Era o requisito não funcional do
/// PRD, e é o que impede o custo de crescer com o número de participantes.
///
/// O extrato e o ranking da rodada são callables: os dois precisam compor
/// palpite + jogo + correção, e o da rodada precisa dos palpites de **todo
/// mundo**, que o cliente não pode ler enquanto o jogo não termina (`PP-7`).
class RankingRepositoryFirebase implements RankingRepository {
  RankingRepositoryFirebase({FirebaseFirestore? db, Callables? callables})
    : _db = db ?? FirebaseFirestore.instance,
      _callables = callables ?? Callables();

  final FirebaseFirestore _db;
  final Callables _callables;

  @override
  Future<Ranking> geral(String poolId, {int limit = 50, int offset = 0}) async {
    final bolao = await _db.doc('boloes/$poolId').get();
    final total = bolao.data()?['activeMembers'] as int? ?? 0;

    // **O Firestore não tem `offset`.** O jeito nativo de paginar é por cursor
    // (`startAfter` do último documento), e o contrato que a tela usa é por
    // deslocamento. Enquanto os dois não se encontram, a página seguinte lê do
    // começo e descarta o que já foi mostrado — o que só é aceitável porque o
    // bolão tem dezenas de participantes, não milhares. Trocar o contrato da
    // tela por cursor é assunto de outra story, não de uma migração que promete
    // não mexer na apresentação.
    final docs = await _db
        .collection('boloes/$poolId/classificacao')
        .orderBy('position')
        .orderBy('displayName')
        .limit(offset + limit)
        .get();

    final pagina = docs.docs.skip(offset).take(limit);
    return Ranking(
      total: total,
      linhas: pagina.map((d) => LinhaRanking.doJson(d.data())).toList(),
    );
  }

  @override
  Future<RankingRodada> daRodada(String poolId, int matchday) async {
    final r = await _callables.chamar<Map<String, dynamic>>('rankingDaRodada', {
      'poolId': poolId,
      'matchday': matchday,
    });
    return RankingRodada.doJson(mapaDaCallable(r));
  }

  @override
  Future<Extrato> extrato(String poolId, int matchday) async {
    final r = await _callables.chamar<Map<String, dynamic>>('extratoDaRodada', {
      'poolId': poolId,
      'matchday': matchday,
    });
    return Extrato.doJson(mapaDaCallable(r));
  }
}
