import 'package:riverpod_annotation/riverpod_annotation.dart';

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

part 'events_repository.g.dart';

class EventsRepository {
  EventsRepository(this._api);

  final ApiClient _api;

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

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

  Future<String> createEvent(Event event) async {
    final data = await _api.post('/events/index.php', event.toJson());
    return data['id'] as String;
  }

  Future<void> updateEvent(Event event) async {
    await _api.put('/events/detail.php', event.toJson(), params: {'id': event.id});
  }

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

  Future<bool> isRegistered(String eventId) async {
    final data = await _api.get(
      '/events/register.php',
      params: {'event_id': eventId},
    );
    return (data['registered'] as bool?) ?? false;
  }

  Future<void> register(String eventId) async {
    await _api.post('/events/register.php', {'event_id': eventId});
  }

  Future<void> unregister(String eventId) async {
    await _api.delete('/events/register.php', params: {'event_id': eventId});
  }

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

@Riverpod(keepAlive: true)
EventsRepository eventsRepository(EventsRepositoryRef ref) {
  return EventsRepository(ref.watch(apiClientProvider));
}

@riverpod
Stream<List<Event>> eventsStream(EventsStreamRef ref) {
  return ref.watch(eventsRepositoryProvider).watchEvents();
}
