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

class TestableAbstractMenuBuilder extends AbstractMenuBuilder {
    static readonly menuName = 'TestableMenu'

    public build(): MenuItem | MenuGroup | null {
        return { label: 'my_menu' };
    }

    public createGroup(
        label: string,
        icon?: IconItem,
        children: MenuItems = [],
        actions: Array<MenuItem> = []
    ): MenuGroup {
        return super.createGroup(label, icon, children, actions)
    }

    public createItem (
        label: string,
        icon?: IconItem,
        to: string = '',
        type: MENU_LINK_TYPE = MENU_LINK_TYPE.INTERNAL,
    ): MenuItem {
        return super.createItem(label, icon, to, type)
    }

    public buildSubmenu(menuBuilder: typeof AbstractMenuBuilder) {
        return super.buildSubmenu(menuBuilder)
    }
}

let runtimeConfig: RuntimeConfig
let ability: AnyAbility
let organizationProfile: organizationState
let accessProfile: AccessProfile
let menuBuilder: TestableAbstractMenuBuilder

beforeEach(()=> {
    runtimeConfig = vi.fn() as any as RuntimeConfig
    ability = vi.fn() as any as AnyAbility
    organizationProfile = vi.fn() as any as organizationState
    accessProfile = vi.fn() as any as AccessProfile

    menuBuilder = new TestableAbstractMenuBuilder(runtimeConfig, ability, organizationProfile, accessProfile)
})



describe('getMenuName', () => {
    test('get name', () => {
        expect(menuBuilder.getMenuName()).toEqual('TestableMenu')
    })
})

describe('createGroup', () => {
    test('simple group', () => {
        const label = 'my_menu'
        const icon = {name: 'my_icon'}
        const children = [{label: 'submenu', type: MENU_LINK_TYPE.INTERNAL, active: true}]
        const actions = [{label: 'action', type: MENU_LINK_TYPE.INTERNAL, active: true}]

        const result = menuBuilder.createGroup(label, icon, children, actions)

        expect(result).toEqual({label, icon, children, actions})
    })

    test('default values', () => {
        const result = menuBuilder.createGroup('my_menu')

        expect(result).toEqual(
            {label: 'my_menu', icon: undefined, children: [], actions: []}
        )
    })
})

describe('createItem', () => {
    test('simple item', () => {
        const label = 'my_menu'
        const icon = {name: 'my_icon'}
        const to = 'https://domain.com/foo/bar'
        const type = MENU_LINK_TYPE.EXTERNAL

        const result = menuBuilder.createItem(label, icon, to, type)

        expect(result).toEqual({ icon, label, to, type, active: false })
    })

    test('default values', () => {
        const result = menuBuilder.createItem('my_menu')

        expect(result).toEqual(
            {label: 'my_menu', icon: undefined, to: '', type: MENU_LINK_TYPE.INTERNAL, active: false}
        )
    })

    test('prepend https on external url', () => {
        const item = menuBuilder.createItem('my_menu', undefined, 'domain.com', MENU_LINK_TYPE.EXTERNAL)
        expect(item.to).toEqual('https://domain.com')
    })

    test('complete V1 links (server side)', () => {

        runtimeConfig.baseUrlAdminLegacy = 'https://admin.opentalent.fr'

        const item = menuBuilder.createItem('my_menu', undefined, '/my_page', MENU_LINK_TYPE.V1)

        expect(item.to).toEqual('https://admin.opentalent.fr/my_page')
    })

    test('complete V1 links (client side)', () => {

        runtimeConfig.baseUrlAdminLegacy = ''
        // @ts-ignore
        runtimeConfig.public = {baseUrlAdminLegacy: 'https://admin.opentalent.fr'}

        const item = menuBuilder.createItem('my_menu', undefined, '/my_page', MENU_LINK_TYPE.V1)

        expect(item.to).toEqual('https://admin.opentalent.fr/my_page')
    })
})

describe('buildSubmenu', () => {
    test('should call given menu build method', () => {
        expect(menuBuilder.buildSubmenu(TestableAbstractMenuBuilder)).toEqual({ label: 'my_menu' })
    })
})
