import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../../../core/api/api_client.dart';
import '../domain/bracket.dart';

part 'brackets_repository.g.dart';

class BracketsRepository {
  BracketsRepository(this._api);

  final ApiClient _api;

  Future<List<Bracket>> fetchBrackets() async {
    final data = await _api.get('/brackets/index.php');
    final list = (data['brackets'] as List?) ?? [];
    return list.whereType<Map<String, dynamic>>().map(Bracket.fromJson).toList();
  }

  Future<Bracket?> getBracket(String id) async {
    try {
      final data = await _api.get('/brackets/detail.php', params: {'id': id});
      return Bracket.fromJson(data);
    } on ApiException catch (e) {
      if (e.statusCode == 404) return null;
      rethrow;
    }
  }

  Future<String> createBracket(Bracket bracket) async {
    final data = await _api.post('/brackets/index.php', bracket.toJson());
    return data['id'] as String;
  }

  Future<Bracket> updateBracket(Bracket bracket) async {
    final data = await _api.put(
      '/brackets/detail.php',
      bracket.toJson(),
      params: {'id': bracket.id},
    );
    return Bracket.fromJson(data);
  }

  Future<void> deleteBracket(String id) async {
    await _api.delete('/brackets/detail.php', params: {'id': id});
  }

  Future<void> updateMatch(
    String bracketId,
    String roundLabel,
    BracketMatch match,
  ) async {
    final bracket = await getBracket(bracketId);
    if (bracket == null) return;
    final rounds = bracket.rounds.map((round) {
      if (round.label != roundLabel) return round;
      final updatedMatches = round.matches
          .map((m) => m.id == match.id ? match : m)
          .toList(growable: false);
      return round.copyWith(matches: updatedMatches);
    }).toList(growable: false);
    await updateBracket(bracket.copyWith(rounds: rounds));
  }

  Stream<List<Bracket>> watchBrackets() async* {
    yield await fetchBrackets();
    await for (final _ in Stream<void>.periodic(const Duration(seconds: 30))) {
      yield await fetchBrackets();
    }
  }
}

@Riverpod(keepAlive: true)
BracketsRepository bracketsRepository(BracketsRepositoryRef ref) {
  return BracketsRepository(ref.watch(apiClientProvider));
}

@riverpod
Stream<List<Bracket>> bracketsStream(BracketsStreamRef ref) {
  return ref.watch(bracketsRepositoryProvider).watchBrackets();
}
