import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/utils/toasts.dart'; import 'package:eatvio_app/features/payment/models/promo_apply_response.dart'; import 'package:eatvio_app/features/payment/models/promo_code_model.dart'; import 'package:eatvio_app/features/payment/models/promo_validate_response.dart'; import 'package:eatvio_app/features/payment/presentation/widgets/promo_code_gate_bottom_sheet.dart'; import 'package:eatvio_app/features/payment/presentation/widgets/promo_code_modal.dart'; import 'package:eatvio_app/features/payment/presentation/widgets/sbp_banks_bottom_sheet.dart'; import 'package:eatvio_app/features/payment/repositories/payment_repository.dart'; import 'package:flutter/material.dart'; /// Оркестрирует флоу оплаты консультации: /// applied rehydrate → (или гейт → форма) → apply при необходимости → SbpBanks. Future showConsultationPaymentFlow( BuildContext context, { required int planId, Future Function(BuildContext)? showGate, Future Function( BuildContext, { Future Function(String)? onValidate, Future Function()? onRemove, PromoCodeModel? initialPromo, })? showForm, Future Function(BuildContext, {required int planId})? showSbp, Future Function({ required int planId, required String promoCode, })? validatePromo, Future Function({ required int planId, required String promoCode, })? applyPromo, Future Function(int planId)? listApplied, Future Function(int planId)? removePromo, }) async { final gate = showGate ?? _showGate; final form = showForm ?? _showForm; final sbp = showSbp ?? _showSbp; final validate = validatePromo ?? _defaultValidatePromo; final apply = applyPromo ?? _defaultApplyPromo; final findApplied = listApplied ?? _defaultFindApplied; final remove = removePromo ?? _defaultRemovePromo; final existing = await findApplied(planId); if (!context.mounted) return; if (existing != null) { final formResult = await form( context, initialPromo: existing, onRemove: () => remove(planId), onValidate: (code) => _mapValidateResponse( validate(planId: planId, promoCode: code), ), ); if (formResult == null || !context.mounted) return; if (formResult.hasPromoCode && !formResult.alreadyApplied) { final applied = await _tryApplyPromo( apply: apply, planId: planId, promoCode: formResult.code!, ); if (!applied || !context.mounted) return; } if (!context.mounted) return; await sbp(context, planId: planId); return; } final gateChoice = await gate(context); if (gateChoice == null || !context.mounted) return; if (gateChoice) { final formResult = await form( context, onValidate: (code) => _mapValidateResponse( validate(planId: planId, promoCode: code), ), ); if (formResult == null || !context.mounted) return; if (formResult.hasPromoCode && !formResult.alreadyApplied) { final applied = await _tryApplyPromo( apply: apply, planId: planId, promoCode: formResult.code!, ); if (!applied || !context.mounted) return; } } if (!context.mounted) return; await sbp(context, planId: planId); } Future _showGate(BuildContext context) { return showPromoCodeGateBottomSheet(context); } Future _showForm( BuildContext context, { Future Function(String)? onValidate, Future Function()? onRemove, PromoCodeModel? initialPromo, }) { return ItvioPromoCodeModal.show( context, onValidate: onValidate, onRemove: onRemove, initialPromo: initialPromo, ); } Future _showSbp(BuildContext context, {required int planId}) { return showSbpBanksBottomSheet(context, planId: planId); } Future _defaultValidatePromo({ required int planId, required String promoCode, }) { return sl().validatePromoCode( planId: planId, promoCode: promoCode, ); } Future _defaultApplyPromo({ required int planId, required String promoCode, }) { return sl().applyPromoCode( planId: planId, promoCode: promoCode, ); } Future _defaultFindApplied(int planId) { return sl().findAppliedPromoForPlan(planId); } Future _defaultRemovePromo(int planId) async { try { final response = await sl().removePromoCode(planId: planId); if (response.success) return true; showErrorToast(response.error ?? 'Не удалось убрать промокод.'); return false; } catch (_) { showErrorToast('Не удалось убрать промокод. Попробуйте позже'); return false; } } Future _mapValidateResponse( Future request, ) async { try { final response = await request; if (!response.valid) { return PromoValidation.failure( response.error ?? 'Промокод невалиден.', ); } return PromoValidation.success( discountPercent: response.discountPercent, discountAmountRub: response.discountAmountRub, originalAmountRub: response.originalAmountRub, finalAmountRub: response.finalAmountRub, ); } catch (_) { return const PromoValidation.failure( 'Не удалось проверить промокод. Попробуйте позже', ); } } Future _tryApplyPromo({ required Future Function({ required int planId, required String promoCode, }) apply, required int planId, required String promoCode, }) async { try { final response = await apply(planId: planId, promoCode: promoCode); if (response.success) return true; showErrorToast(response.error ?? 'Не удалось применить промокод.'); return false; } catch (_) { showErrorToast('Не удалось применить промокод. Попробуйте позже'); return false; } }