import 'dart:async';
import 'dart:io';

import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/product.dart';
import 'package:aitrainer_app/model/purchase.dart';
import 'package:aitrainer_app/repository/customer_repository.dart';
import 'package:aitrainer_app/repository/description_repository.dart';
import 'package:aitrainer_app/repository/mautic_repository.dart';
import 'package:aitrainer_app/repository/split_test_respository.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/purchase_service.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/purchases.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:purchases_flutter/offering_wrapper.dart';

part 'sales_event.dart';
part 'sales_state.dart';

class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
  List<Product> product2Display = [];
  List<String> productText2Display = ["WorkoutTest annual", "WorkoutTest montly"];
  final SplitTestRepository splitTestRepository = SplitTestRepository();

  int productSet = -1;
  final DescriptionRepository descriptionRepository = DescriptionRepository();
  SalesBloc() : super(SalesInitial());

  String? salesText;
  String? premiumFunctions = "";
  String? trial = "";

  Future<void> init() async {
    if (Cache().userLoggedIn == null) {
      throw Exception("Please log in");
    }

    salesText = splitTestRepository.getSplitTestValue("sales_page_text_a");
    if (salesText == null || salesText!.isEmpty) {
      salesText = descriptionRepository.getDescriptionByName("sales_page_text_a");
    }
    print("sales Text: $salesText");
    getProductsTexts();

    premiumFunctions = descriptionRepository.getDescriptionByName("premium_functions");
    if (premiumFunctions == null || premiumFunctions!.isEmpty) {
      premiumFunctions = "";
    }

    trial = descriptionRepository.getDescriptionByName("trial");
    if (trial == null || trial!.isEmpty) {
      trial = "";
    }

    await RevenueCatPurchases().getOfferings();
    this.getProductSet();
    Track().track(TrackingEvent.sales_page);
  }

  @override
  Stream<SalesState> mapEventToState(
    SalesEvent event,
  ) async* {
    try {
      if (event is SalesLoad) {
        log(" -- start SalesLoad");
        yield SalesLoading();
        await init();
        yield SalesReady();
        log(" -- finish SalesLoad");
      } else if (event is SalesPurchase) {
        if (Cache().hasPurchased) {
          throw Exception("You have already a successfull subscription");
        }
        yield SalesLoading();
        final int productId = event.productId;
        log("Requesting purchase for: " + productId.toString());
        Track().track(TrackingEvent.purchase_request);
        final Product? selectedProduct = this.getSelectedProduct(productId);
        log("SelectedProduct for purchase $selectedProduct");
        if (selectedProduct != null) {
          await RevenueCatPurchases().makePurchase(selectedProduct);
          if (Cache().hasPurchased) {
            Purchase purchase = Purchase(customerId: Cache().userLoggedIn!.customerId!, productId: productId);
            purchase.dateAdd = DateTime.now();
            purchase.purchaseSum = 0;
            purchase.currency = "EUR";
            await PurchaseApi().savePurchase(purchase);
            Track().track(TrackingEvent.purchase_successful, eventValue: selectedProduct.localizedPrice.toString());
            CustomerRepository customerRepository = CustomerRepository();
            customerRepository.customer = Cache().userLoggedIn;
            MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository);
            await mauticRepository.sendMauticPurchase();
          }
          yield SalesSuccessful();
        } else {
          yield SalesError(message: "No selected product");
        }
      }
    } on Exception catch (ex) {
      yield SalesError(message: ex.toString());
    }
  }

  void getProductsTexts() {
    Product product;
    if (product2Display.isNotEmpty) {
      String salesButtonText;
      product2Display.forEach((element) {
        product = element;
        if (product.sort == 3) {
          salesButtonText = descriptionRepository.getDescriptionByName("sales_button_monthly");
          productText2Display[1] = salesButtonText.replaceFirst(RegExp(r'localizedPrice'), product.localizedPrice!);
        } else if (product.sort == 1) {
          salesButtonText = descriptionRepository.getDescriptionByName("sales_button_yearly");
          productText2Display[0] = salesButtonText.replaceFirst(RegExp(r'localizedPrice'), product.localizedPrice!);
        }
      });
    }
    print("product Text $productText2Display");

    splitTestRepository.getSplitTestValue("product_set_2");

    return;
  }

  Product? getSelectedProduct(int productId) {
    Product? prod;
    for (var product in this.product2Display) {
      if (product.productId == productId) {
        prod = product;
      }
    }
    return prod;
  }

  String getLocalizedPrice(String productId, Product product) {
    String price = "";
    Offering? offering = RevenueCatPurchases().offering;
    if (offering != null) {
      for (var package in offering.availablePackages) {
        log("PlatformProduct " + package.toString());
        if (productId == package.product.identifier) {
          price = package.product.priceString;
          if (price.contains(r'HUF')) {
            price = price.replaceAll(RegExp(r'HUF'), 'Ft');
            price = price.replaceAll(RegExp(r'\,00'), "");
          }
          break;
        }
      }
    } else {
      log(" !!! No Offering");
    }
    if (price.isEmpty) {
      price = Platform.isAndroid ? product.priceAndroid.toString() : product.priceIos.toString();
    }
    return price;
  }

  void getProductSet() {
    List<Product>? products = Cache().products;
    if (products == null) {
      return;
    }

    String productSetString = splitTestRepository.getSplitTestValue("product_set_2");
    log("ProductSetString: $productSetString");
    try {
      productSet = int.parse(productSetString);
    } on Exception catch (e) {
      log("Define the right productset! $e");
      productSet = 2;
    }

    log("ProductSet: $productSet");

    for (var elem in products) {
      Product product = elem;

      if (product.productSet == productSet) {
        String? platformProductId;
        if (product.productIdAndroid == null || product.productIdIos == null) {
          log("Define the product ID for the different Platforms!!");
        } else {
          platformProductId = Platform.isAndroid ? product.productIdAndroid! : product.productIdIos!;
        }

        if (platformProductId == null) {
          log("Not defined platform product id!!");
          platformProductId = "";
        }
        product.localizedPrice = getLocalizedPrice(platformProductId, product);
        log("product with localized price: $product");
        product2Display.add(product);
      }
    }

    product2Display.sort((a, b) {
      return a.sort < b.sort ? -1 : 1;
    });

    this.getProductsTexts();
  }
}