/**
 * @jest-environment jsdom
 */
const fs = require('fs')
const yaml = require('js-yaml');
var beautify = require("json-beautify");
import Ajv from 'ajv'

import ECommerce from ".."

import {
    CartAction,
    DeliveryAction,
    DrugProperties,
    ECommerceTypes,
    ItemAction,
    ListAction,
    ListType,
    ItemType,
    StockStatus
} from "../typings";

import { CurrencyCode } from "../../../core/commonTypes";
import { MediaType, ContentBlock, MediaCatalog, UserCatalog } from "../../Navigation/typings";
import { ICatalogRepository } from "../../../core/repositories/catalog/CatalogRepository";
import CfCore from "../../../core/CfCore";

let mockCatalogRepository: ICatalogRepository;

let windowSpy
let mockSender;
let mockImpressionManager = {
    on: () => { }
};

describe('ECommerce - API', () => {
    let schemaValidate;
    const device_id = 'asdf'

    beforeAll(() => {
        const schemaPath = `${__dirname}/../../../../scripts/standardized-schema.json`
        const jsonSchema = fs.readFileSync(schemaPath, 'utf8')
        const ajv = new Ajv()

        schemaValidate = ajv.compile(JSON.parse(jsonSchema))

        mockSender = {
            add() { return false }
        }

        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 deliver a "Checkout" event with the correct format', async () => {
        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: "1",
            cart_price: 10,
            currency: CurrencyCode.EUR,
            tax: 0,
            items: [{
                id: '111',
                price: 90,
                type: ItemType.Drug,
                quantity: 1,
                promo_id: '11111',
                currency: CurrencyCode.EUR,
                stock_status: StockStatus.InStock
            }],
            cart_id: '11',
            is_successful: true
        }

        await ECommerce.logCheckoutEvent(event)

        const valid = schemaValidate(senderSpy.mock.calls[0][2])

        if (!valid) {
            console.log(beautify(senderSpy.mock.calls[0][2], null, 2, 80))
            console.log(schemaValidate.errors)
        }

        expect(valid).toEqual(true)
    })

    it('Should deliver a "Delivery" event', () => {
        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: "1",
            action: DeliveryAction.Delivered,
            order_id: '11',
        }

        ECommerce.logDeliveryEvent(event)
        const valid = schemaValidate(senderSpy.mock.calls[0][2])

        expect(valid).toEqual(true)

    })


    it('Should deliver a "Cart" event', async () => {
        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: "1",
            action: CartAction.AddItem,
            cart_price: 10,
            currency: CurrencyCode.EUR,
            item: {
                id: '111',
                type: ItemType.Drug,
                price: 90,
                quantity: 1,
                promo_id: '11111',
                currency: CurrencyCode.EUR,
                stock_status: StockStatus.InStock
            },
        }

        await ECommerce.logCartEvent(event)

        const valid = schemaValidate(senderSpy.mock.calls[0][2])

        if (!valid) {
            console.log(beautify(senderSpy.mock.calls[0][2], null, 2, 80))
            console.log(schemaValidate.errors)
        }
        expect(valid).toEqual(true)
    })

    it('Should deliver an "Item" event', async () => {
        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = 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, {})

        const valid = schemaValidate(senderSpy.mock.calls[0][2])

        if (!valid) {
            console.log(beautify(senderSpy.mock.calls[0][2], null, 2, 80))
            console.log(schemaValidate.errors)
        }

        expect(valid).toEqual(true)
    })

})
