/**
 * @jest-environment jsdom
 */

const fs = require('fs')
const yaml = require('js-yaml');
var beautify = require("json-beautify");

import Ajv from 'ajv'

import CfCore from "../../../core/CfCore"
import CatalogRepository, { ICatalogRepository } from "../../../core/repositories/catalog/CatalogRepository";
import ECommerce from "../../ECommerce";
import { DeliveryAction, DrugProperties, ECommerceTypes } from "../../ECommerce/typings";
import Navigation from ".."

import {
    AppAction,
    MediaType,
    ContentBlock,
    IdentityAction,
    MediaAction,
    MediaCatalog,
    NavigationTypes,
    NudgeAction,
    NudgeResponseType,
    UserInfo,
    UserCatalog,
} from "../typings";

let windowSpy
let mockSender;
let mockCatalogRepository: ICatalogRepository;

class MockImpressionsDetector {
    start() { }
    stop() { }
    restart() { }
}



describe('Navigation - API', () => {
    let schemaValidate;

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

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

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

    afterEach(() => {
        // to remove the singleton instance
        (CfCore as any).instance = null
    })

    it('Should deliver an "App" event', () => {
        const DEFAULT_DEVICE_ID = 'web_sdk_device_id'

        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(mockSender as any, MockImpressionsDetector, false, ContentBlock.Core, DEFAULT_DEVICE_ID, false)

        const event = {
            action: AppAction.Background,
            start_time : 0
        }

        Navigation.logIngestEvent(NavigationTypes.App, event)


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


    })

    it('Should deliver a "Media" event', () => {
        const DEFAULT_DEVICE_ID = 'web_sdk_device_id'

        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(mockSender as any, MockImpressionsDetector, false, ContentBlock.Core, DEFAULT_DEVICE_ID, false)

        const event = {
            type: MediaType.Video,
            id: 'id-media-event',
            action: MediaAction.Play,
            time: 11111
        }

        Navigation.logIngestEvent(NavigationTypes.Media, 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 "Media" event with e-elearning type', () => {
        const DEFAULT_DEVICE_ID = 'web_sdk_device_id'

        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(mockSender as any, MockImpressionsDetector, false, ContentBlock.Core, DEFAULT_DEVICE_ID, false)

        const event = {
            contentBlock: ContentBlock.ELearning,
            type: MediaType.Audio,
            id: 'id-media-event',
            action: MediaAction.Play,
            time: 111
        }

        Navigation.logIngestEvent(NavigationTypes.Media, event)
        console.log(beautify(senderSpy.mock.calls[0][2], null, 2, 80))
        const valid = schemaValidate(senderSpy.mock.calls[0][2])
        if (!valid) console.log(schemaValidate.errors)

        expect(valid).toEqual(true)
    })

    it('Should deliver a "Page" event', () => {
        const DEFAULT_DEVICE_ID = 'web_sdk_device_id'

        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(mockSender as any, MockImpressionsDetector, false, ContentBlock.Core, DEFAULT_DEVICE_ID, false)

        const event = { path: '/mypath', title: 'page-title' }

        Navigation.logIngestEvent(NavigationTypes.Page, 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 "Login" event', () => {
        const DEFAULT_DEVICE_ID = 'web_sdk_device_id'

        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(mockSender as any, MockImpressionsDetector, false, ContentBlock.Core, DEFAULT_DEVICE_ID, false)

        const props: UserInfo = {
            action: IdentityAction.Login,
            user_props: {}
        }

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

        expect(valid).toEqual(true)
    })

    it('Should deliver a "Delivery" event with the content block set to ECommerce - no call to setCurrentBlock', () => {
        const DEFAULT_DEVICE_ID = 'web_sdk_device_id'

        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(mockSender as any, MockImpressionsDetector, false, ContentBlock.Core, DEFAULT_DEVICE_ID, false)

        const event = {
            id: "11",
            action: DeliveryAction.Delivered,
            order_id: "1",
        }

        ECommerce.logDeliveryEvent(event)

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

        expect(valid).toEqual(true)
    })


    it('Should deliver a "Delivery" event with the contentBlock set to ECommerce - call to setCurrentBlock', () => {
        const DEFAULT_DEVICE_ID = 'web_sdk_device_id'

        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(mockSender as any, MockImpressionsDetector, false, ContentBlock.Core, DEFAULT_DEVICE_ID, true)

        const event = {
            id: "1",
            action: DeliveryAction.Delivered,
            order_id: "11",
        }
        Navigation.setCurrentBlock(ContentBlock.ELearning)

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

        expect(valid).toEqual(true)
    })


    it('Should deliver a "PushNotification" event', () => {
        const DEFAULT_DEVICE_ID = 'web_sdk_device_id'

        const senderSpy = jest.spyOn(mockSender, 'add')
        const bsCore = CfCore.createInstance(mockSender as any, MockImpressionsDetector, false, ContentBlock.Core, DEFAULT_DEVICE_ID, false)

        const event = {
            nudge_id: 111,
            type: NudgeResponseType.Push,
            response: {
                action: NudgeAction.Discard
            }
        }

        Navigation.logPushNotificationEvent(event)

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

        expect(valid).toEqual(true)

    })

})
