import { fixture, assert, nextFrame, html } from '@open-wc/testing'
import { AmfBase, AmfDefinitions } from '@api-client/core/browser.js'
import { AmfLoader } from '../AmfLoader.js'
import { DomEventsAmfStore } from '../../../src/amf/store/DomEventsAmfStore.js'
import ApiAnnotationDocumentElement from '../../../src/elements/amf/ApiAnnotationDocument.element.js'
import '../../../src/define/amf/api-annotation-document.js'

describe('ApiAnnotationDocumentElement', () => {
  const loader = new AmfLoader()
  const store = new DomEventsAmfStore(window)
  store.listen()
  const apiFile = 'annotated-api'

  async function basicFixture(properties?: AmfBase.IApiCustomDomainProperty[]): Promise<ApiAnnotationDocumentElement> {
    return fixture(html`<api-annotation-document .customProperties="${properties}"></api-annotation-document>`)
  }

  describe('a11y', () => {
    let element: ApiAnnotationDocumentElement
    let model: AmfDefinitions.IAmfDocument
    before(async () => {
      model = await loader.getGraph(apiFile)
      store.amf = model
    })

    beforeEach(async () => {
      const shape = loader.getShape(model, 'ComplexAnnotations')
      element = await basicFixture(shape.customDomainProperties)
      await nextFrame()
    })

    it('is accessible', async () => {
      await assert.isAccessible(element)
    })
  })

  describe('Compact model', () => {
    describe('Model computations', () => {
      let model: AmfDefinitions.IAmfDocument
      before(async () => {
        model = await loader.getGraph(apiFile)
        store.amf = model
      })

      let element: ApiAnnotationDocumentElement
      beforeEach(async () => {
        element = await basicFixture()
      })

      it('computes hasCustomProperties when no annotations', () => {
        const shape = loader.getShape(model, 'NoAnnotations')
        element.customProperties = shape.customDomainProperties
        assert.isFalse(element.hasCustomProperties)
      })

      it('computes hasCustomProperties when has the annotations', () => {
        const shape = loader.getShape(model, 'ComboType')
        element.customProperties = shape.customDomainProperties
        assert.isTrue(element.hasCustomProperties)
      })

      it('computes the list of annotations', () => {
        const shape = loader.getShape(model, 'ComboType')
        element.customProperties = shape.customDomainProperties
        assert.typeOf(element.customProperties, 'array')
        assert.lengthOf(element.customProperties, 3)
      })

      it('renders a nil annotation', async () => {
        const shape = loader.getShape(model, 'notRequiredRepeatable')
        element.customProperties = shape.customDomainProperties
        await nextFrame()
        const node = element.shadowRoot!.querySelectorAll('.custom-property')[0]
        assert.ok(node, 'Annotation container is rendered')
        const label = node.querySelector('.name') as HTMLElement
        assert.ok(label, 'Annotation label is rendered')
        const labelValue = label.innerText.toLowerCase()
        assert.equal(labelValue, 'annotationtest')
      })

      // APIMF-1710
      it('does not render a value for a nil annotation', async () => {
        const shape = loader.getShape(model, 'notRequiredRepeatable')
        element.customProperties = shape.customDomainProperties
        await nextFrame()
        const node = element.shadowRoot!.querySelector('.custom-property')!
        assert.ok(node, 'Annotation container is rendered')
        const value = node.querySelector('.scalar-value') as HTMLElement
        assert.isEmpty(value.textContent!.trim(), 'Annotation value is not rendered')
      })

      it('renders a scalar annotation', async () => {
        const shape = loader.getShape(model, 'ErrorResource')
        element.customProperties = shape.customDomainProperties
        await nextFrame()
        const node = element.shadowRoot!.querySelector('.custom-property')!
        assert.ok(node, 'Annotation container is rendered')
        const label = node.querySelector('.name') as HTMLElement
        assert.ok(label, 'Annotation label is rendered')
        const labelValue = label.innerText!.toLowerCase()
        assert.equal(labelValue, 'deprecated')
        const value = node.querySelector('.scalar-value')
        assert.ok(value, 'Annotation value is rendered')
        const scalarList = node.querySelectorAll('.scalar-value')
        assert.equal(scalarList.length, 1, 'Scalar value is rendered')
      })

      it('renders a complex annotation', async () => {
        const shape = loader.getShape(model, 'ComplexAnnotations')
        element.customProperties = shape.customDomainProperties
        await nextFrame()
        const node = element.shadowRoot!.querySelector('.custom-property')!
        assert.ok(node, 'Annotation container is rendered')
        const label = node.querySelector('.name') as HTMLElement
        assert.ok(label, 'Annotation label is rendered')
        const labelValue = label.innerText.toLowerCase()
        assert.equal(labelValue, 'clearancelevel')
        const objectNodes = node.querySelectorAll('.object-property')
        assert.equal(objectNodes.length, 2, 'has all properties rendered')
      })
    })
  })
})
