import 'package:flutter_bloc/flutter_bloc.dart';

import '../../../../core/payment/payment_gateway.dart';
import '../../../../core/storage/token_storage.dart';
import '../../../../core/resources/data_state.dart';
import '../../../../core/usecase/use_case.dart';
import '../../domain/use_cases/ad_reward_usecase.dart';
import '../../domain/use_cases/buy_card_usecase.dart';
import '../../domain/use_cases/get_shop_usecase.dart';
import '../../domain/use_cases/purchase_usecase.dart';
import '../../domain/use_cases/select_card_usecase.dart';
import 'shop_event.dart';
import 'shop_state.dart';
import 'shop_status.dart';

class ShopBloc extends Bloc<ShopEvent, ShopBlocState> {
  final GetShopUseCase getShopUseCase;
  final BuyCardUseCase buyCardUseCase;
  final SelectCardUseCase selectCardUseCase;
  final PurchaseUseCase purchaseUseCase;
  final AdRewardUseCase adRewardUseCase;
  final PaymentGateway gateway;
  final TokenStorage storage;

  ShopBloc(
    this.getShopUseCase,
    this.buyCardUseCase,
    this.selectCardUseCase,
    this.purchaseUseCase,
    this.adRewardUseCase,
    this.gateway,
    this.storage,
  ) : super(ShopBlocState.initial()) {
    on<LoadShopEvent>((event, emit) => _load(emit));

    on<BuyCardEvent>((event, emit) =>
        _action(emit, () => buyCardUseCase(event.cardId)));

    on<SelectCardEvent>((event, emit) =>
        _action(emit, () => selectCardUseCase(event.cardId)));

    on<PurchaseEvent>((event, emit) => _action(emit, () => _purchase(event)));

    on<AdRewardEvent>((event, emit) => _action(
          emit,
          () async {
            final res = await adRewardUseCase(
                'dev-ad-${DateTime.now().millisecondsSinceEpoch}');
            if (res is DataSuccess) {
              return const DataSuccess('سکه رایگان دریافت شد');
            }
            return DataError<String>(res.error!);
          },
        ));
  }

  /// جریانِ خرید: ابتدا پرداختِ فروشگاهی (native) اجرا می‌شود، سپس مدرکِ خرید
  /// (token/purchaseData/signature) برای اعتبارسنجی به بک‌اند فرستاده می‌شود و
  /// در پایان، خرید در فروشگاه consume می‌شود.
  Future<DataState<String>> _purchase(PurchaseEvent event) async {
    // برای پرداختِ native به SKUِ فروشگاه نیاز است؛ اگر تنظیم نشده باشد از
    // شناسه‌ی کاتالوگ استفاده می‌کنیم (حالتِ توسعه/تک‌فروشگاهی).
    final sku = event.sku.isNotEmpty ? event.sku : event.productId;

    // شماره‌ی موبایل را به‌عنوان payload می‌فرستیم تا خرید در پنلِ فروشگاه
    // قابلِ ردیابی باشد.
    final mobile = await storage.readMobile() ?? '';

    final PurchaseResult result;
    try {
      result = await gateway.purchase(sku, payload: mobile);
    } catch (e) {
      return DataError<String>('خطا در پرداخت: $e');
    }
    if (!result.success) {
      return DataError<String>('خرید انجام نشد یا لغو شد');
    }

    final verify = await purchaseUseCase(PurchaseParams(
      store: gateway.store,
      kind: event.kind,
      productId: event.productId,
      token: result.token,
      purchaseData: result.purchaseData,
      signature: result.signature,
    ));

    // پس از تأییدِ بک‌اند، خرید را در فروشگاه نهایی/مصرف می‌کنیم.
    if (verify is DataSuccess && result.onConfirmed != null) {
      try {
        await result.onConfirmed!();
      } catch (_) {/* consume ناموفق حیاتی نیست */}
    }
    return verify;
  }

  Future<void> _load(Emitter<ShopBlocState> emit) async {
    emit(state.copyWith(loadStatus: ShopLoading()));
    final res = await getShopUseCase(const NoParams());
    if (res is DataSuccess) {
      emit(state.copyWith(loadStatus: ShopLoaded(res.data!)));
    } else {
      emit(state.copyWith(loadStatus: ShopLoadError(res.error!)));
    }
  }

  /// اجرای یک عملیات، نمایش وضعیت و سپس بازخوانی کاتالوگ.
  Future<void> _action(
    Emitter<ShopBlocState> emit,
    Future<DataState<String>> Function() action,
  ) async {
    if (state.busy) return;
    emit(state.copyWith(actionStatus: ActionLoading()));
    final res = await action();
    if (res is DataSuccess) {
      emit(state.copyWith(actionStatus: ActionSuccess(res.data!)));
      await _load(emit);
    } else {
      emit(state.copyWith(actionStatus: ActionError(res.error!)));
    }
  }
}
