// Implementação HTTP — o backend NestJS da fase 1.
//
// Continua aqui porque `MG-9` ainda não desligou o servidor antigo: enquanto a
// migração não é verificada ponta a ponta (`MG-8`), poder voltar para ele é o
// que separa "trocamos o backend" de "não temos backend".
import '../../../core/api/api_client.dart';
import 'boloes_repository.dart';

class BoloesRepositoryHttp implements BoloesRepository {
  BoloesRepositoryHttp(this._api);

  final ApiClient _api;

  @override
  Future<List<BolaoResumo>> meus() async {
    final r = await _api.get<List<dynamic>>('/pools');
    return r.cast<Map<String, dynamic>>().map(BolaoResumo.doJson).toList();
  }

  @override
  Future<List<Competicao>> competicoes() async {
    final r = await _api.get<List<dynamic>>('/pools/competitions');
    return r.cast<Map<String, dynamic>>().map(Competicao.doJson).toList();
  }

  @override
  Future<Bolao> criar({
    required String nome,
    required String competitionCode,
    required int rodadaInicial,
    required int rodadaFinal,
    int? pontosExato,
    int? pontosVencedorSaldo,
    int? pontosVencedor,
    List<String>? ordemDesempate,
  }) async {
    // Regras omitidas caem no default do servidor (10/5/3). Mandar os valores
    // só quando o admin mexeu evita gravar "customizado" o que é o padrão.
    final regras = <String, dynamic>{
      'pointsExact': ?pontosExato,
      'pointsWinnerDiff': ?pontosVencedorSaldo,
      'pointsWinner': ?pontosVencedor,
      'tiebreakOrder': ?ordemDesempate,
    };

    final r = await _api.post<Map<String, dynamic>>(
      '/pools',
      body: {
        'name': nome,
        'competitionCode': competitionCode,
        'matchdayFrom': rodadaInicial,
        'matchdayTo': rodadaFinal,
        if (regras.isNotEmpty) 'rules': regras,
      },
    );
    return Bolao.doJson(r);
  }

  /// Altera as regras. O servidor recusa com 409 depois do primeiro palpite —
  /// e essa recusa é fluxo esperado, não erro.
  @override
  Future<void> alterarRegras(
    String poolId, {
    required int pontosExato,
    required int pontosVencedorSaldo,
    required int pontosVencedor,
    required List<String> ordemDesempate,
  }) async {
    await _api.patch<Map<String, dynamic>>(
      '/pools/$poolId/rules',
      body: {
        'pointsExact': pontosExato,
        'pointsWinnerDiff': pontosVencedorSaldo,
        'pointsWinner': pontosVencedor,
        'tiebreakOrder': ordemDesempate,
      },
    );
  }

  @override
  Future<Rodada> rodada(String poolId, int matchday) async {
    final r = await _api.get<Map<String, dynamic>>(
      '/pools/$poolId/matchdays/$matchday',
    );
    return Rodada.doJson(r);
  }

  @override
  Future<ResultadoEnvio> palpitar(
    String poolId,
    List<({String matchId, int casa, int fora})> palpites,
  ) async {
    final r = await _api.post<Map<String, dynamic>>(
      '/pools/$poolId/predictions',
      body: {
        'predictions': palpites
            .map(
              (p) => {
                'matchId': p.matchId,
                'homeScore': p.casa,
                'awayScore': p.fora,
              },
            )
            .toList(),
      },
    );
    return ResultadoEnvio.doJson(r);
  }

  @override
  Future<({String poolId, String poolName, bool jaParticipava})>
  entrarPorConvite(String token) async {
    final r = await _api.post<Map<String, dynamic>>(
      '/pools/join',
      body: {'token': token},
    );
    return (
      poolId: r['poolId'] as String,
      poolName: r['poolName'] as String,
      jaParticipava: r['jaParticipava'] as bool,
    );
  }

  @override
  Future<({String token, DateTime expiraEm})> gerarConvite(
    String poolId,
  ) async {
    final r = await _api.post<Map<String, dynamic>>('/pools/$poolId/invite');
    return (
      token: r['token'] as String,
      expiraEm: DateTime.parse(r['expiresAt'] as String),
    );
  }

  /// Palpites de todos num jogo (PP-7). Vem vazio enquanto o jogo não termina.
  @override
  Future<PalpitesDoJogo> palpitesDoJogo(String poolId, String matchId) async {
    final r = await _api.get<Map<String, dynamic>>(
      '/pools/$poolId/matches/$matchId/predictions',
    );
    return PalpitesDoJogo.doJson(r);
  }

  /// Correção manual do placar pelo admin (PR-10). Devolve o impacto para a
  /// tela poder dizer quantos foram reapurados e avisados.
  @override
  Future<({int afetados, int avisos})> corrigirPlacar(
    String poolId,
    String matchId,
    int casa,
    int fora,
  ) async {
    final r = await _api.patch<Map<String, dynamic>>(
      '/pools/$poolId/matches/$matchId/score',
      body: {'homeScore': casa, 'awayScore': fora},
    );
    return (
      afetados: r['afetados'] as int? ?? 0,
      avisos: r['avisos'] as int? ?? 0,
    );
  }

  /// Invalida o convite atual sem gerar outro — para quando o link caiu no
  /// lugar errado e o admin ainda não quer convidar mais ninguém.
  @override
  Future<void> invalidarConvite(String poolId) async {
    await _api.delete<void>('/pools/$poolId/invite');
  }
}
