import 'package:flutter/foundation.dart';

import 'package:pshared/models/payment/payment.dart';
import 'package:pshared/provider/organizations.dart';
import 'package:pshared/provider/payment/multiple/quotation.dart';
import 'package:pshared/provider/resource.dart';
import 'package:pshared/service/payment/multiple.dart';
import 'package:pshared/utils/exception.dart';

class MultiPaymentProvider extends ChangeNotifier {
  late OrganizationsProvider _organization;
  late MultiQuotationProvider _quotation;

  Resource<List<Payment>> _payments = Resource(data: null);

  List<Payment> get payments => _payments.data ?? [];
  bool get isLoading => _payments.isLoading;
  Exception? get error => _payments.error;
  bool get isReady =>
      _payments.data != null && !_payments.isLoading && _payments.error == null;

  void update(
    OrganizationsProvider organization,
    MultiQuotationProvider quotation,
  ) {
    _organization = organization;
    _quotation = quotation;
  }

  Future<List<Payment>> pay({
    String? idempotencyKey,
    String? clientPaymentRef,
    Map<String, String>? metadata,
  }) async {
    if (!_organization.isOrganizationSet) {
      throw StateError('Organization is not set');
    }

    final quoteRef = _quotation.quotation?.quoteRef;
    if (quoteRef == null || quoteRef.isEmpty) {
      throw StateError('Multiple quotation reference is not set');
    }

    final expiresAt = _quotation.quoteExpiresAt;
    if (expiresAt != null && expiresAt.isBefore(DateTime.now().toUtc())) {
      throw StateError('Multiple quotation is expired');
    }

    _setResource(_payments.copyWith(isLoading: true, error: null));
    try {
      final response = await MultiplePaymentsService.payByQuote(
        _organization.current.id,
        quoteRef,
        idempotencyKey: idempotencyKey,
        clientPaymentRef: clientPaymentRef,
        metadata: metadata,
      );

      _setResource(
        _payments.copyWith(data: response, isLoading: false, error: null),
      );
    } catch (e) {
      _setResource(
        _payments.copyWith(data: [], isLoading: false, error: toException(e)),
      );
    }

    return _payments.data ?? [];
  }

  void reset() {
    _setResource(Resource(data: null));
  }

  void _setResource(Resource<List<Payment>> payments) {
    _payments = payments;
    notifyListeners();
  }
}
