import { describe, test, it, expect } from 'vitest'
import MenuComposer from "~/services/layout/menuComposer";
import {RuntimeConfig} from "@nuxt/schema";
import {AnyAbility} from "@casl/ability/dist/types";
import {AccessProfile, LayoutState, organizationState} from "~/types/interfaces";
import {MenuBuilder, MenuGroup, MenuItem} from "~/types/layout";
import {MENU_LINK_TYPE} from "~/types/enum/layout";
import AbstractMenuBuilder from "~/services/layout/menuBuilder/abstractMenuBuilder";



describe('build', () => {
    test('simple call', () => {
        // @ts-ignore
        const runtimeConfig = vi.fn() as RuntimeConfig
        // @ts-ignore
        const ability = vi.fn() as AnyAbility
        // @ts-ignore
        const organizationProfile = vi.fn() as organizationState
        // @ts-ignore
        const accessProfile = vi.fn() as AccessProfile
        // @ts-ignore
        const layoutState = vi.fn() as LayoutState

        layoutState.menus = {}
        layoutState.menusOpened = {}

        const item1 = {label: 'item1', type: MENU_LINK_TYPE.INTERNAL} as MenuItem
        const group1 = {label: 'group1', children: []} as MenuGroup
        const group2 = {label: 'group1', children: [{label: 'item2', type: MENU_LINK_TYPE.INTERNAL}]} as MenuGroup

        // @ts-ignore
        const dummyBuilder1 = vi.fn() as MenuBuilder
        const dummyBuilderClass1 = vi.fn(() => dummyBuilder1)
        dummyBuilder1.getMenuName = vi.fn(() => 'dummy1')
        dummyBuilder1.build = vi.fn(() => item1)

        // @ts-ignore
        const dummyBuilder2 = vi.fn() as MenuBuilder
        const dummyBuilderClass2 = vi.fn(() => dummyBuilder2)
        dummyBuilder2.getMenuName = vi.fn(() => 'dummy2')
        dummyBuilder2.build = vi.fn(() => group1)

        // @ts-ignore
        const dummyBuilder3 = vi.fn() as MenuBuilder
        const dummyBuilderClass3 = vi.fn(() => dummyBuilder3)
        dummyBuilder3.getMenuName = vi.fn(() => 'dummy3')
        dummyBuilder3.build = vi.fn(() => group2)

        // @ts-ignore
        const dummyBuilder4 = vi.fn() as MenuBuilder
        const dummyBuilderClass4 = vi.fn(() => dummyBuilder4)
        dummyBuilder4.getMenuName = vi.fn(() => 'dummy4')
        dummyBuilder4.build = vi.fn(() => null)

        // @ts-ignore
        MenuComposer.builders = [ dummyBuilderClass1, dummyBuilderClass2, dummyBuilderClass3, dummyBuilderClass4 ]

        MenuComposer.build(runtimeConfig, ability, organizationProfile, accessProfile, layoutState)

        expect(dummyBuilderClass1).toHaveBeenCalledOnce()
        expect(dummyBuilderClass1).toHaveBeenCalledWith(runtimeConfig, ability, organizationProfile, accessProfile)
        expect(dummyBuilder1.build).toHaveBeenCalledOnce()

        expect(dummyBuilderClass2).toHaveBeenCalledOnce()
        expect(dummyBuilderClass2).toHaveBeenCalledWith(runtimeConfig, ability, organizationProfile, accessProfile)
        expect(dummyBuilder2.build).toHaveBeenCalledOnce()

        expect(dummyBuilderClass3).toHaveBeenCalledOnce()
        expect(dummyBuilderClass3).toHaveBeenCalledWith(runtimeConfig, ability, organizationProfile, accessProfile)
        expect(dummyBuilder3.build).toHaveBeenCalledOnce()

        expect(dummyBuilderClass4).toHaveBeenCalledOnce()
        expect(dummyBuilderClass4).toHaveBeenCalledWith(runtimeConfig, ability, organizationProfile, accessProfile)
        expect(dummyBuilder4.build).toHaveBeenCalledOnce()

        expect(layoutState.menus).toEqual({
            'dummy1': item1,
            'dummy2': group1,
            'dummy3': group2
        })

        expect(layoutState.menusOpened).toEqual({
            'dummy3': false
        })
    })
})
