import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:pshared/models/auto_refresh_mode.dart'; import 'package:pshared/models/payment/quote/status_type.dart'; import 'package:pshared/provider/payment/quotation/quotation.dart'; class QuotationController extends ChangeNotifier { QuotationProvider? _quotation; Timer? _ticker; void update(QuotationProvider quotation) { if (identical(_quotation, quotation)) return; _quotation?.removeListener(_handleQuotationChanged); _quotation = quotation; _quotation?.addListener(_handleQuotationChanged); _handleQuotationChanged(); } bool get isLoading => _quotation?.isLoading ?? false; Exception? get error => _quotation?.error; bool get canRefresh => _quotation?.canRefresh ?? false; bool get isReady => _quotation?.isReady ?? false; AutoRefreshMode get autoRefreshMode => _quotation?.autoRefreshMode ?? AutoRefreshMode.on; DateTime? get quoteExpiresAt => _quotation?.quoteExpiresAt; Duration? get timeLeft { final expiresAt = quoteExpiresAt; if (expiresAt == null) return null; return expiresAt.difference(DateTime.now().toUtc()); } bool get isExpired { final remaining = timeLeft; if (remaining == null) return false; return remaining <= Duration.zero; } QuoteStatusType get quoteStatus { if (isLoading) return QuoteStatusType.loading; if (error != null) return QuoteStatusType.error; if (_quotation?.quotation == null) return QuoteStatusType.missing; if (isExpired) return QuoteStatusType.expired; return QuoteStatusType.active; } bool get hasLiveQuote => isReady && _quotation?.quotation != null && !isExpired; void setAutoRefreshMode(AutoRefreshMode mode) { _quotation?.setAutoRefreshMode(mode); } void refreshQuotation() { _quotation?.refreshQuotation(); } void _handleQuotationChanged() { _syncTicker(); notifyListeners(); } void _syncTicker() { final expiresAt = quoteExpiresAt; if (expiresAt == null) { _stopTicker(); return; } final remaining = expiresAt.difference(DateTime.now().toUtc()); if (remaining <= Duration.zero) { _stopTicker(); return; } _ticker ??= Timer.periodic(const Duration(seconds: 1), (_) { final expiresAt = quoteExpiresAt; if (expiresAt == null) { _stopTicker(); return; } final remaining = expiresAt.difference(DateTime.now().toUtc()); if (remaining <= Duration.zero) { _stopTicker(); } notifyListeners(); }); } void _stopTicker() { _ticker?.cancel(); _ticker = null; } @override void dispose() { _quotation?.removeListener(_handleQuotationChanged); _stopTicker(); super.dispose(); } }