import '../../../../data/network/i_api_client.dart'; import '../../../../data/cache/cache_store.dart'; import '../models/schedule_item_model.dart'; class CalendarService { static const _prefix = '/api/v1/schedule-items'; final IApiClient _apiClient; final CacheInvalidator _invalidator; CalendarService({ required IApiClient apiClient, required CacheInvalidator invalidator, }) : _apiClient = apiClient, _invalidator = invalidator; Future> getEventsForDay(DateTime date) async { final start = DateTime(date.year, date.month, date.day); final end = DateTime(date.year, date.month, date.day, 23, 59, 59); return getEventsForRange(start, end); } Future> getEventsForRange( DateTime start, DateTime end, ) async { final startParam = Uri.encodeQueryComponent( start.toUtc().toIso8601String(), ); final endParam = Uri.encodeQueryComponent(end.toUtc().toIso8601String()); final response = await _apiClient.get>( '$_prefix?start_at=$startParam&end_at=$endParam', ); final data = response.data; if (data == null) { throw StateError('Invalid getEventsForRange response: empty payload'); } return data .map((item) => item as Map) .map(ScheduleItemModel.fromJson) .toList(growable: false); } Future getEventById(String id) async { final response = await _apiClient.get>('$_prefix/$id'); final data = response.data; if (data == null) { throw StateError('Invalid getEventById response: empty payload'); } return ScheduleItemModel.fromJson(data); } Future addEvent(ScheduleItemModel event) async { final response = await _apiClient.post>( _prefix, data: event.toCreateJson(), ); final data = response.data; if (data == null) { throw StateError('Invalid addEvent response: empty payload'); } final created = ScheduleItemModel.fromJson(data); _invalidateEventCache(created); return created; } Future updateEvent(ScheduleItemModel event) async { final response = await _apiClient.patch>( '$_prefix/${event.id}', data: event.toUpdateJson(), ); final data = response.data; if (data == null) { throw StateError('Invalid updateEvent response: empty payload'); } final updated = ScheduleItemModel.fromJson(data); _invalidateEventCache(updated); return updated; } Future archiveEvent(String id) async { final event = await getEventById(id); final updatedEvent = await updateEvent( event.copyWith(status: ScheduleStatus.archived), ); _invalidateEventCache(updatedEvent); return updatedEvent; } Future deleteEvent(String id) async { final event = await getEventById(id); _invalidateEventCache(event); await _apiClient.delete('$_prefix/$id'); } void _invalidateEventCache(ScheduleItemModel event) { var current = DateTime( event.startAt.year, event.startAt.month, event.startAt.day, ); final end = DateTime( event.endAt?.year ?? event.startAt.year, event.endAt?.month ?? event.startAt.month, event.endAt?.day ?? event.startAt.day, ); while (!current.isAfter(end)) { _invalidator.invalidateCalendarDay(current); current = current.add(const Duration(days: 1)); } } }