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';

import 'package:pweb/providers/quotation/auto_refresh.dart';


class QuotationController extends ChangeNotifier {
  QuotationProvider? _quotation;
  AutoRefreshMode _autoRefreshMode = AutoRefreshMode.on;
  final QuotationAutoRefreshController _autoRefreshController =
      QuotationAutoRefreshController();
  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 => _autoRefreshMode;

  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) {
    if (_autoRefreshMode == mode) return;
    _autoRefreshMode = mode;
    _syncAutoRefresh();
    notifyListeners();
  }

  void refreshQuotation() {
    _quotation?.refreshQuotation();
  }

  void _handleQuotationChanged() {
    _syncAutoRefresh();
    _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;
  }

  void _syncAutoRefresh() {
    final quotation = _quotation;
    if (quotation == null) {
      _autoRefreshController.reset();
      return;
    }

    final isAutoRefreshEnabled = _autoRefreshMode == AutoRefreshMode.on;
    _autoRefreshController.setEnabled(isAutoRefreshEnabled);
    final canAutoRefresh = isAutoRefreshEnabled && quotation.canRefresh;
    _autoRefreshController.sync(
      isLoading: quotation.isLoading,
      canRefresh: canAutoRefresh,
      expiresAt: quoteExpiresAt,
      onRefresh: _refreshQuotation,
    );
  }

  Future<void> _refreshQuotation() async {
    await _quotation?.refreshQuotation();
  }

  @override
  void dispose() {
    _quotation?.removeListener(_handleQuotationChanged);
    _autoRefreshController.dispose();
    _stopTicker();
    super.dispose();
  }
}