import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:pshared/provider/account.dart'; import 'package:pweb/models/flow_status.dart'; import 'package:pweb/models/resend/action_result.dart'; import 'package:pweb/models/resend/avaliability.dart'; class SignupConfirmationCardController extends ChangeNotifier { SignupConfirmationCardController({ required AccountProvider accountProvider, Duration defaultCooldown = const Duration(seconds: 60), }) : _accountProvider = accountProvider, _defaultCooldown = defaultCooldown; final AccountProvider _accountProvider; final Duration _defaultCooldown; Timer? _cooldownTimer; DateTime? _cooldownUntil; int _cooldownRemainingSeconds = 0; FlowStatus _resendState = FlowStatus.idle; String? _email; int get cooldownRemainingSeconds => _cooldownRemainingSeconds; ResendAvailability get resendAvailability { final email = _email; if (email == null || email.isEmpty) { return ResendAvailability.missingEmail; } if (_resendState == FlowStatus.submitting) { return ResendAvailability.resending; } if (_cooldownRemainingSeconds > 0) { return ResendAvailability.cooldown; } return ResendAvailability.available; } void updateEmail(String? email) { final trimmed = email?.trim(); if (_email == trimmed) return; _email = trimmed; notifyListeners(); } void initialize({String? email}) { updateEmail(email); startDefaultCooldown(); } void startDefaultCooldown() { _startCooldown(_defaultCooldown); } Future resendVerificationEmail() async { switch (resendAvailability) { case ResendAvailability.missingEmail: return ResendActionResult.missingEmail; case ResendAvailability.cooldown: return ResendActionResult.cooldown; case ResendAvailability.resending: return ResendActionResult.inProgress; case ResendAvailability.available: break; } _setResendState(FlowStatus.submitting); try { final email = _email; if (email == null || email.isEmpty) { _setResendState(FlowStatus.idle); return ResendActionResult.missingEmail; } await _accountProvider.resendVerificationEmail(email); _startCooldown(_defaultCooldown); return ResendActionResult.sent; } finally { _setResendState(FlowStatus.idle); } } @override void dispose() { _cooldownTimer?.cancel(); super.dispose(); } void _startCooldown(Duration duration) { _cooldownTimer?.cancel(); _cooldownUntil = DateTime.now().add(duration); _syncRemaining(); if (_cooldownRemainingSeconds <= 0) { _cooldownUntil = null; notifyListeners(); return; } _cooldownTimer = Timer.periodic(const Duration(seconds: 1), (timer) { _syncRemaining(); if (_cooldownRemainingSeconds <= 0) { timer.cancel(); _cooldownUntil = null; notifyListeners(); } }); } void _syncRemaining() { final remaining = _cooldownRemaining(); if (remaining == _cooldownRemainingSeconds) return; _cooldownRemainingSeconds = remaining; notifyListeners(); } int _cooldownRemaining() { final until = _cooldownUntil; if (until == null) return 0; final remaining = until.difference(DateTime.now()).inSeconds; return remaining < 0 ? 0 : remaining; } void _setResendState(FlowStatus state) { if (_resendState == state) return; _resendState = state; notifyListeners(); } }