import 'package:flutter/foundation.dart'; import '../models/bar_tab.dart'; import '../models/closed_tab.dart'; import '../services/bar_tab_service.dart'; class HistoryViewModel extends ChangeNotifier { final BarTabService barTabService; HistoryViewModel({required this.barTabService}); static const int _pageSize = 20; List _closedTabs = []; List _openTabs = []; List _customerNames = []; String? _selectedCustomer; int _offset = 0; int _totalCount = 0; bool _isLoading = false; bool _hasLoaded = false; bool _isLoadingMore = false; String? _errorMessage; String _searchQuery = ''; List get closedTabs { return _closedTabs .where((tab) => _matchesCustomer(tab.customerName)) .toList(); } List get openTabs { return _openTabs .where((tab) => _matchesCustomer(tab.customerName)) .toList(); } List get customerNames => _customerNames; String? get selectedCustomer => _selectedCustomer; bool get isLoading => _isLoading; bool get hasLoaded => _hasLoaded; bool get isLoadingMore => _isLoadingMore; bool get hasMore => _closedTabs.length < _totalCount; String? get errorMessage => _errorMessage; Future ensureLoaded() async { if (_hasLoaded || _isLoading) return; await load(); } Future load() async { if (_isLoading) return; _isLoading = true; _errorMessage = null; notifyListeners(); try { final results = await Future.wait([ _fetchPage(offset: 0), barTabService.getClosedTabCount(customerName: _selectedCustomer), barTabService.getDistinctCustomerNames(), barTabService.getOpenTabs(includeRemoved: true), ]); _closedTabs = (results[0] as List).toList() ..sort(_compareClosedTabs); _totalCount = results[1] as int; _openTabs = (results[3] as List).toList()..sort(_compareOpenTabs); _customerNames = { ...(results[2] as List), ..._openTabs.map((tab) => tab.customerName), }.toList()..sort(); _offset = _closedTabs.length; } catch (e) { debugPrint('HistoryViewModel: load error: $e'); _errorMessage = 'Could not load tab history.'; } finally { _hasLoaded = true; _isLoading = false; notifyListeners(); } } Future loadMore() async { if (_isLoadingMore || !hasMore) return; _isLoadingMore = true; notifyListeners(); try { final more = await _fetchPage(offset: _offset); _closedTabs = [..._closedTabs, ...more]..sort(_compareClosedTabs); _offset = _closedTabs.length; } catch (e) { debugPrint('HistoryViewModel: loadMore error: $e'); _errorMessage = 'Could not load more tabs.'; } finally { _isLoadingMore = false; notifyListeners(); } } Future> _fetchPage({required int offset}) { return barTabService.getClosedTabsPaginated( limit: _pageSize, offset: offset, customerName: _selectedCustomer, ); } int _compareClosedTabs(ClosedTab a, ClosedTab b) { final byClosedAt = b.closedAt.compareTo(a.closedAt); if (byClosedAt != 0) return byClosedAt; return b.id.compareTo(a.id); } int _compareOpenTabs(BarTab a, BarTab b) { final byOpenedAt = b.openedAt.compareTo(a.openedAt); if (byOpenedAt != 0) return byOpenedAt; return b.id.compareTo(a.id); } void search(String query) { _searchQuery = query; notifyListeners(); } bool _matchesCustomer(String customerName) { if (_selectedCustomer != null && customerName != _selectedCustomer) { return false; } if (_searchQuery.isEmpty) return true; return customerName.toLowerCase().contains(_searchQuery.toLowerCase()); } Future filterByCustomer(String? customerName) async { _selectedCustomer = customerName; _searchQuery = ''; _offset = 0; _closedTabs = []; await load(); } }