package ai.causalfoundry.rnsdk.ecommerce;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

import ai.causalfoundry.android.sdk.e_commerce.builders.CfLogCancelCheckoutEvent;
import ai.causalfoundry.android.sdk.e_commerce.builders.CfLogCartEvent;
import ai.causalfoundry.android.sdk.e_commerce.builders.CfLogCheckoutEvent;
import ai.causalfoundry.android.sdk.e_commerce.builders.CfLogDeliveryEvent;
import ai.causalfoundry.android.sdk.e_commerce.builders.CfLogItemEvent;
import ai.causalfoundry.android.sdk.e_commerce.builders.CfLogItemReportEvent;
import ai.causalfoundry.android.sdk.e_commerce.builders.CfLogItemRequestEvent;
import ai.causalfoundry.android.sdk.e_commerce.builders.CfLogItemVerificationEvent;
import ai.causalfoundry.android.sdk.e_commerce.catalog.CfEComCatalog;
import ai.causalfoundry.android.sdk.e_commerce.impression_listerner.CfItemImpressionListener;


public class CfLogECom extends ReactContextBaseJavaModule {

    private final ReactApplicationContext reactContext;

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

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

    /**
     * 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 catalogObject, String meta,
                             Boolean updateImmediately) {
        new CfLogItemEvent.Builder()
                .setItemAction(viewAction).setItem(itemString)
                .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 CfLogCartEvent.Builder()
                .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 shopMode          is required to log the mode for the shopping, delivery or pickup.
     * @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 shopMode,
                                 String orderListString, String meta,
                                 Boolean updateImmediately) {

        if(shopMode == null || shopMode.isEmpty()){
            shopMode = "delivery";
        }

        new CfLogCheckoutEvent.Builder()
                .setOrderId(orderId).setCartId(cartId).isSuccessful(isSuccessful)
                .setPrice(price).setCurrency(currencyCode)
                .setShopMode(shopMode)
                .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 isUrgent              is to notify if the delivery is is an urgent delivery.
     * @param dateTimeMillis        is to get the timeInMillis for the delivery.
     * @param deliveryCoordinates   is to provide the delivery location coordinates
     * @param dispatchCoordinates   is to provide the dispatch location coordinates
     * @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, Boolean isUrgent,
                                 double dateTimeMillis, String deliveryCoordinates,
                                 String dispatchCoordinates, String meta,
                                 Boolean updateImmediately) {
        new CfLogDeliveryEvent.Builder()
                .setOrderId(orderId).setDeliveryAction(action)
                .setDeliveryId(deliveryId)
                .isUrgent(isUrgent)
                .setDeliveryDateTime((long) dateTimeMillis)
                .setDeliveryCoordinates(deliveryCoordinates)
                .setDispatchCoordinates(dispatchCoordinates)
                .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 CfLogCancelCheckoutEvent.Builder()
                .setCheckoutId(id)
                .setCancelType(type)
                .addItemList(itemsList)
                .setCancelReason(reason)
                .setMeta(meta).updateImmediately(updateImmediately)
                .build();
    }


    /**
     * logItemReportEvent is used to log the event an item is reported.
     *
     * @param itemObject        is for the providing item Id and type for the item in question.The
     *                          object should be based on the ItemTypeModel or a string that can
     *                          be converted to the object with proper param names.
     * @param storeObject       is for the providing store object details for the item report if any.
     *                          The object should be based on the StoreObject or a string that can be
     *                          converted to the object with proper param names.
     * @param reportObject      is for the providing report object details for the item report if any.
     *                          The object should be based on the ReportObject or a string that can
     *                          be converted to the object with proper param names.
     * @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 logItemReportEvent(String itemObject, String storeObject, String reportObject,
                                   String meta,
                                   Boolean updateImmediately) {

        new CfLogItemReportEvent.Builder()
                .setItem(itemObject)
                .setStoreObject(storeObject)
                .setReportObject(reportObject)
                .setMeta(meta).updateImmediately(updateImmediately)
                .build();
    }


    /**
     * logItemRequestEvent is used to log the event an item is requested.
     *
     * @param requestId         is for the providing system id for the request for product.
     * @param itemName          is for the providing Item name requested by the user.
     * @param manufacturer      is for the providing manufacturer for the item requested by the user.
     * @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 logItemRequestEvent(String requestId, String itemName, String manufacturer,
                                    String meta,
                                    Boolean updateImmediately) {

        new CfLogItemRequestEvent.Builder()
                .setItemRequestId(requestId)
                .setItemName(itemName)
                .setItemManufacturer(manufacturer)
                .setMeta(meta).updateImmediately(updateImmediately)
                .build();
    }


    /**
     * logItemVerificationEvent is used to log the event an item is verified/scanned by the user.
     *
     * @param scanChannel       is for the providing scan channel used for verification.
     * @param scanType          is for the providing scan Type used for verification.
     * @param isSuccessful      is for the providing if verification was successful or not.
     * @param itemInfo          is for the providing item info details returned by the verification.
     *                          The object should be based on the ItemInfoObject or a string that can
     *                          be converted to the object with proper param names.
     * @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 logItemVerificationEvent(String scanChannel, String scanType,
                                         Boolean isSuccessful, String itemInfo,
                                         String meta,
                                         Boolean updateImmediately) {

        CfLogItemVerificationEvent.Builder cfLogItemVerificationEvent = new CfLogItemVerificationEvent.Builder()
                .setScanChannel(scanChannel)
                .setScanType(scanType)
                .isSuccessful(isSuccessful)
                .setMeta(meta).updateImmediately(updateImmediately);

        if(itemInfo != null){
            cfLogItemVerificationEvent.setItemInfo(itemInfo);
        }

        cfLogItemVerificationEvent.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.
     */
    @ReactMethod
    public void logItemImpressionEvent(String recyclerId, String visibleItems) {

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

    /**
     * Drug catalog values
     *
     * @param itemId           Drug id in the system
     * @param drugCatalogModel Props for the drug item
     */
    @ReactMethod
    public void updateDrugCatalog(String itemId, String drugCatalogModel) {
        CfEComCatalog.INSTANCE.updateDrugCatalog(itemId, drugCatalogModel);
    }

    /**
     * Grocery catalog values
     *
     * @param itemId           Grocery id in the system
     * @param groceryItemModel Props for the grocery item
     */
    @ReactMethod
    public void updateGroceryCatalog(String itemId, String groceryItemModel) {
        CfEComCatalog.INSTANCE.updateGroceryCatalog(itemId, groceryItemModel);
    }

    /**
     * Blood catalog values
     *
     * @param itemId           Item id in the system
     * @param bloodCatalogModel Props for the blood item
     */
    @ReactMethod
    public void updateBloodCatalog(String itemId, String bloodCatalogModel) {
        CfEComCatalog.INSTANCE.updateBloodCatalog(itemId, bloodCatalogModel);
    }

    /**
     * Oxygen catalog values
     *
     * @param itemId           Item id in the system
     * @param oxygenCatalogModel Props for the oxygen item
     */
    @ReactMethod
    public void updateOxygenCatalog(String itemId, String oxygenCatalogModel) {
        CfEComCatalog.INSTANCE.updateOxygenCatalog(itemId, oxygenCatalogModel);
    }

    /**
     * Medical Equipment catalog values
     *
     * @param itemId           Item id in the system
     * @param medicalEquipmentCatalogModel Props for the Medical Equipment item
     */
    @ReactMethod
    public void updateMedicalEquipmentCatalog(String itemId, String medicalEquipmentCatalogModel) {
        CfEComCatalog.INSTANCE.updateMedicalEquipmentCatalog(itemId, medicalEquipmentCatalogModel);
    }

    /**
     * Facility catalog values
     *
     * @param facilityId           Facility id in the system
     * @param facilityCatalogModel Props for the facility element
     */
    @ReactMethod
    public void updateFacilityCatalog(String facilityId, String facilityCatalogModel) {
        CfEComCatalog.INSTANCE.updateFacilityCatalog(facilityId, facilityCatalogModel);
    }


}