package ai.benshi.rnsdk.ecommerce;

import android.util.Log;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import ai.benshi.android.sdk.e_commerce.builders.BsLogCancelCheckoutEvent;
import ai.benshi.android.sdk.e_commerce.builders.BsLogCartEvent;
import ai.benshi.android.sdk.e_commerce.builders.BsLogCheckoutEvent;
import ai.benshi.android.sdk.e_commerce.builders.BsLogDeliveryEvent;
import ai.benshi.android.sdk.e_commerce.builders.BsLogItemEvent;
import ai.benshi.android.sdk.e_commerce.builders.BsLogScheduleDeliveryEvent;
import ai.benshi.android.sdk.e_commerce.catalog_models.DrugCatalogModel;
import ai.benshi.android.sdk.e_commerce.catalog_models.MedicalEquipmentCatalogModel;
import ai.benshi.android.sdk.e_commerce.event_types.ItemType;
import ai.benshi.android.sdk.e_commerce.impression_listerner.BshItemImpressionListener;
import ai.benshi.android.sdk.e_commerce.impression_listerner.event_model.ItemImpressionModel;


public class BsLogECom extends ReactContextBaseJavaModule {

    private final ReactApplicationContext reactContext;

    public BsLogECom(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "BsLogECom";
    }

    /**
     * logItemEvent refers to an item in E-commerce. It can be called when a user taps on an item to
     * view it in full screen and also when a user taps on the description of the item to view more
     * details. This event refers to the item view log that reflects the user has seen specific
     * item or view its details.
     *
     * @param viewAction        is required to set Type for the type of log in this case, if a
     *                          user is viewing an item or its details.
     * @param itemString        required to pass the whole item as a JSON String object as well.
     *                          You can use the POJO ItemModel to parse the data in the required
     *                          format and pass that to this function as a string to log the event.
     * @param searchId          is used to associate the search id with the item being viewed by
     *                          the user. It is required to track if the item is a result of some
     *                          search performed by the user in the app.
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
    @ReactMethod
    public void logItemEvent(String viewAction, String itemString, String searchId,
                             String catalogObject, String meta,
                             Boolean updateImmediately) {
        new BsLogItemEvent.Builder().init(reactContext)
                .setItemAction(viewAction).setItem(itemString).setSearchId(searchId)
                .setCatalogProperties(catalogObject)
                .setMeta(meta).updateImmediately(updateImmediately)
                .build();
    }

    /**
     * logCartEvent is used to log the events related to the cart. You can use this event to log
     * When an item was added or removed from the cart.
     *
     * @param cartId            used to log the cartId the event is logged for. It is recommended to
     *                          include the cartIds for the defined list types so that they can be
     *                          tracked.
     * @param cartAction        is required to pass the actions for cart the logged is triggered on.
     *                          By default, the SDK provides 2 main list actions for e-commerce apps.
     *                          Which includes addItem and removeItem
     * @param itemString        is used to pass the whole item as a JSON String object as well. You
     *                          can use the POJO ItemModel to parse the data in the required format
     *                          and pass that to this function as a string to log the event.
     * @param price             is required to log the total price for the cart being logged. Details
     *                          about the cart are to be provided in the catalog.
     * @param currency          is required to log the currency for cart price being logged. Details
     *                          about the cart are to be provided in the catalog.
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
    @ReactMethod
    public void logCartEvent(String cartId, String cartAction,
                             String itemString, float price, String currency, String meta,
                             Boolean updateImmediately) {
        new BsLogCartEvent.Builder().init(reactContext)
                .setCartId(cartId).setCartAction(cartAction)
                .setItem(itemString).setCartPrice(price)
                .setCurrency(currency)
                .setMeta(meta).updateImmediately(updateImmediately)
                .build();
    }

    /**
     * logCheckoutEvent is to track the successful use cases for the order placement. it can track
     * KPIs for the order being placed based on the ratio of how many orders were successfully and
     * how many were not and what are the order aspects.
     *
     * @param orderId           is for the orderId being placed. In case of not being placed and not
     *                          having a valid orderId, you can pass the cartId instead.
     * @param cartId            is for the cart being checked out.
     * @param isSuccessful      is for the order if it was placed successfully or not.
     * @param price             is required to log the total price of the order being logged.
     *                          Price format should be per the currency selected.
     * @param currencyCode      is required to log the currency for the order logged. Currency
     *                          Should be in ISO 4217 format. For ease, SDK provides the enums
     *                          CountryCode to log the currency so that it would be easy to log.
     *                          You can also use the string function to provide the currency.
     * @param orderListString   can be used to add the item being ordered to the checkout list.
     *                          Order items should be in a valid format. With elements of the
     *                          order Object as: OrderItem(itemID, price, quantity, promoId)
     *                          Promo Id can be an empty string or no value at all if the item
     *                          does not have a promo offer that is obtained by the user. You can
     *                          add multiple addOrder functions to one checkout event to include
     *                          all the items in order.
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
    @ReactMethod
    public void logCheckoutEvent(String orderId, String cartId, boolean isSuccessful, float price, String currencyCode,
                                 String orderListString, String meta,
                                 Boolean updateImmediately) {

        new BsLogCheckoutEvent.Builder().init(reactContext)
                .setOrderId(orderId).setCartId(cartId).isSuccessful(isSuccessful)
                .setPrice(price).setCurrency(currencyCode)
                .addItemList(orderListString)
                .setMeta(meta).updateImmediately(updateImmediately)
                .build();
    }

    /**
     * logDeliveryEvent is used to log the status for the delivery. It can be used to log the
     * delivered status of the order or partial order. Details about the items in the specific
     * delivery should be provided in the catalog.
     *
     * @param orderId           is required to associate the rating obtained for the order. OrderId
     *                          Should be a valid orderId and can be tracked from the catalog.
     * @param action            is required to set the delivery action for the log. For the order
     *                          being prepared for delivery or left the shipment center or
     *                          delivered to the customer.
     * @param deliveryId        is required to associate the rating obtained for the order.
     *                          deliveryId should be a valid deliveryId and can be tracked from the
     *                          catalog for the items in that specific delivery.
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
    @ReactMethod
    public void logDeliveryEvent(String orderId, String action, String deliveryId, String meta,
                                 Boolean updateImmediately) {
        new BsLogDeliveryEvent.Builder().init(reactContext)
                .setOrderId(orderId).setDeliveryAction(action)
                .setDeliveryId(deliveryId)
                .setMeta(meta).updateImmediately(updateImmediately)
                .build();
    }

    /**
     * logScheduleDeliveryEvent is used to log the status for the delivery. It can be used to log the
     * delivered status of the order or partial order. Details about the items in the specific
     * delivery should be provided in the catalog.
     *
     * @param orderId           is required to associate the rating obtained for the order. OrderId
     *                          Should be a valid orderId and can be tracked from the catalog.
     * @param action            is required to set the delivery action for the log. For the order
     *                          being prepared for delivery or left the shipment center or
     *                          delivered to the customer.
     * @param isUrgent          isUrgent is to mark the log if the delivery is scheduled to be an
     *                          immediate or emergency delivery.
     * @param dateTimeMillis    The timestamp in time in milliseconds format for the date and time
     *                          for which the delivery is set to be scheduled
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
    @ReactMethod
    public void logScheduleDeliveryEvent(String orderId, Boolean isUrgent, String action,
                                         String dateTimeMillis, String meta,
                                 Boolean updateImmediately) {
        new BsLogScheduleDeliveryEvent.Builder().init(reactContext)
                .setOrderId(orderId).isUrgent(isUrgent)
                .setScheduleDeliveryAction(action)
                .setDeliveryDateTime(dateTimeMillis)
                .setMeta(meta).updateImmediately(updateImmediately)
                .build();
    }

    /**
     * logCancelOrderEvent is used to log the event when the order/cart is canceled.
     *
     * @param id                can be used to log the orderId and cartId the event is logged for.
     *                          This should be in accordance to the type provided in the log and
     *                          should represent the actual element being cancelled/discarded.
     * @param type              is the type of checkout element being canceled, cart or order
     * @param itemsList         is required to provide the list of item types that are present
     *                          in the order being cancelled
     * @param reason            is required to define the reason for which the item is being cancelled.
     * @param meta              is to send any other data you want to send with the ingest, can be null.
     * @param updateImmediately is default set to true, you can use that to log events when the app
     *                          goes in the background or closed.
     */
    @ReactMethod
    public void logCancelCheckoutEvent(String id, String type, String itemsList, String reason,
                                         String meta,
                                         Boolean updateImmediately) {

        new BsLogCancelCheckoutEvent.Builder().init(reactContext)
                .setCheckoutId(id)
                .setCancelType(type)
                .addItemList(itemsList)
                .setCancelReason(reason)
                .setMeta(meta).updateImmediately(updateImmediately)
                .build();
    }

    /**
     * Log Impression event is for the recyclerListView events when you are showing results form a
     * list or from a search and log the impressions on that. This will help in logging easily and
     * manages multiple views in a single instance as well
     *
     * @param recyclerId   unique Id for the recyclerListView
     * @param visibleItems the list if visible items at a given moment. This need to be a list of
     *                     ItemModel provided by the SDK so that it can be logged in the required
     *                     format. for implementation you can view the RecyclerListViewScreen for
     *                     how to map and pass the data.
     * @param searchId     is the id for the search associated with the item impression. This needs
     *                     to be included if you are showing results from the search so that it can
     *                     be logged with the impression that what search was performed with the
     *                     search.
     */
    @ReactMethod
    public void logItemImpressionEvent(String recyclerId, String visibleItems, String searchId) {

        if(!visibleItems.isEmpty()){
            BshItemImpressionListener.onCollectionUpdatedRN(recyclerId, searchId, visibleItems);
        }
    }

}