import { AssertionError } from 'node:assert'
import { describe, test, expect, beforeEach, vi } from 'vitest'
import type { RuntimeConfig } from '@nuxt/schema'
import type { AnyAbility } from '@casl/ability/dist/types'
import type { Router } from 'vue-router'
import type { AccessProfile, organizationState } from '~/types/interfaces'
import ParametersMenuBuilder from '~/services/layout/menuBuilder/parametersMenuBuilder'
import type { IconItem, MenuGroup, MenuItem, MenuItems } from '~/types/layout'

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

  public makeChildren(items: Array<{ pageName: string; icon?: string }>) {
    return super.makeChildren(items)
  }
}

let runtimeConfig: RuntimeConfig
let ability: AnyAbility
let organizationProfile: organizationState
let accessProfile: AccessProfile
let menuBuilder: TestableParametersMenuBuilder
let router: Router

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
  // @ts-ignore
  router = vi.fn() as Router

  runtimeConfig.baseUrlAdminLegacy = 'https://mydomain.com/'

  menuBuilder = new TestableParametersMenuBuilder(
    runtimeConfig,
    ability,
    organizationProfile,
    accessProfile,
    router,
  )
})

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

describe('build', () => {
  test('simple call', () => {
    // @ts-ignore
    menuBuilder.makeChildren = vi.fn((items) => {
      if (items.length !== 11) {
        throw new AssertionError()
      }
      return ['foo', 'bar']
    })

    // @ts-ignore
    menuBuilder.createGroup = vi.fn(() => {
      return { children: ['foo', 'bar'] }
    })
    const result = menuBuilder.build()

    expect(result).toEqual({ children: ['foo', 'bar'] })
    expect(menuBuilder.makeChildren).toHaveBeenCalledOnce()
    expect(menuBuilder.createGroup).toHaveBeenCalledOnce()
  })

  test('has no items', () => {
    // @ts-ignore
    menuBuilder.makeChildren = vi.fn((items) => {
      if (items.length !== 11) {
        throw new AssertionError()
      }
      return []
    })
    menuBuilder.createGroup = vi.fn()

    const result = menuBuilder.build()

    expect(result).toEqual(null)
    expect(menuBuilder.makeChildren).toHaveBeenCalledOnce()
    expect(menuBuilder.createGroup).toHaveBeenCalledTimes(0)
  })
})
