/**
 * @jest-environment jsdom
 */
import CfCore from "../../../core/CfCore"
import { CurrencyCode } from "../../../core/commonTypes"
import { ICatalogRepository } from "../../../core/repositories/catalog/CatalogRepository"
import ECommerce from "../../ECommerce"
import {
    DeliveryAction,
    DrugProperties,
    ECommerceTypes,
    ItemAction,
    ItemType,
    StockStatus
} from "../../ECommerce/typings"
import { MediaType, ContentBlock, MediaCatalog, userCatalog } from "../../Navigation/typings"

let windowSpy

const device_id = 'asdf'
const mockImpressionManager = {
    on: () => { }
};
let mockCatalogRepository: ICatalogRepository;

describe('Identification tests', () => {
    beforeAll(() => {

        const mockCurrencyRepository = {
            injectDrug: (userId: string, properties: DrugProperties) => new Promise(r => r()),
            injectUser: (userId: string, properties: userCatalog) => new Promise(r => r()),
            injectMedia: (id: string, type: MediaType, properties: MediaCatalog | {}) => { }
        }

        ECommerce.init(mockCurrencyRepository, mockCatalogRepository)
    })

    beforeEach(() => {
        windowSpy = jest.spyOn(window, "window", "get");
    })

    afterEach(() => {
        // to remove the singleton instance
        (CfCore as any).instance = null
    })
    it('Should use the same ID for device and user when it has not been set', async () => {
        const mockSender = {
            add() { return false }
        }
        const senderSpy = jest.spyOn(mockSender, 'add')
        const cfCore = CfCore.createInstance(
            mockSender as any,
            mockImpressionManager as any,
            false,
            ContentBlock.Core, device_id, false)

        const event = {
            action: ItemAction.View,
            item: {
                id: '111',
                type: ItemType.Drug,
                quantity: 2,
                price: 100,
                currency: CurrencyCode.FKP,
                stock_status: StockStatus.InStock,
                promo_id: 'asdf'
            },
            search_id: "1"
        }

        await ECommerce.logItemEvent(event, {})

        expect(senderSpy).toBeCalledWith(
            expect.stringMatching(device_id),
            expect.stringMatching(device_id),
            expect.anything(),
            expect.anything())
    })


    it('Should use the custom user_id used specifically in this call', async () => {
        const mockSender = {
            add() { return false }
        }
        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(
            mockSender as any,
            mockImpressionManager as any,
            false,
            ContentBlock.Core, device_id, false)

        const event = {
            id: '1111',
            action: DeliveryAction.Delivered,
            order_id: 'order_Id_111',
        }

        await ECommerce.logDeliveryEvent(event, 'new_user_id')

        expect(senderSpy).toBeCalledWith(
            expect.stringMatching('new_user_id'),
            expect.stringMatching(device_id),
            expect.anything(),
            expect.anything())

    })

    it('Should use the custom user_id used specifically in this call', async () => {
        const mockSender = {
            add() { return false }
        }
        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(
            mockSender as any,
            mockImpressionManager as any,
            false,
            ContentBlock.Core, device_id, false)

        const event = {
            id: '1111',
            action: DeliveryAction.Delivered,
            order_id: 'order_Id_111',
        }

        await ECommerce.logDeliveryEvent(event, 'new_user_id')

        expect(senderSpy).toBeCalledWith(
            expect.stringMatching('new_user_id'),
            expect.stringMatching(device_id),
            expect.anything(),
            expect.anything())

    })


    it('Should use the custom user_id used specifically in this call even if the user is logged', async () => {
        const mockSender = {
            add() { return false }
        }
        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(
            mockSender as any,
            mockImpressionManager as any,
            false,
            ContentBlock.Core, device_id, false)

        bsCore.login('real_user_id')

        const event = {
            id: '1111',
            action: DeliveryAction.Delivered,
            order_id: 'order_Id_111',
        }

        await ECommerce.logDeliveryEvent(event, 'new_user_id')

        expect(senderSpy).toBeCalledWith(
            expect.stringMatching('new_user_id'),
            expect.stringMatching(device_id),
            expect.anything(),
            expect.anything())

    })

    it('Should use user_id from logging ', async () => {
        const mockSender = {
            add() { return false }
        }
        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(
            mockSender as any,
            mockImpressionManager as any,
            false,
            ContentBlock.Core, device_id, false)

        bsCore.login('real_user_id')

        const event = {
            id: '1111',
            action: DeliveryAction.Delivered,
            order_id: 'order_Id_111',
        }

        await ECommerce.logDeliveryEvent(event)

        expect(senderSpy).toBeCalledWith(
            expect.stringMatching('real_user_id'),
            expect.stringMatching(device_id),
            expect.anything(),
            expect.anything())
    })
})
