// As part of the optimisation the examples may be referenced in a link
// shared between different payloads. These test are looking for the
// right example for the right payload.

import { test } from '@japa/runner'
import { AmfLoader } from '../AmfLoader.js'
import { AmfSerializer } from '../../../../src/amf/AmfSerializer.js'
import type { IAmfDocument } from '../../../../src/amf/definitions/Amf.js'
import { IApiNodeShape } from '../../../../src/amf/definitions/Shapes.js'

test.group('Payload examples', (group) => {
  const loader = new AmfLoader()
  const jsonMime = 'application/json'
  const xmlMime = 'application/xml'

  let api: IAmfDocument
  let serializer: AmfSerializer
  group.setup(async () => {
    api = await loader.getGraph('amf-helper-api')
    serializer = new AmfSerializer(api)
  })

  test('returns a RAML example for the JSON mime', async ({ assert }) => {
    const shape = loader.lookupRequestPayload(api, '/body-tracking', 'get', jsonMime)
    const result = serializer.payload(shape)

    const { examples } = result.schema as IApiNodeShape

    assert.lengthOf(examples, 2, 'has both examples from the type and the payload')
    const [ex1, ex2] = examples

    assert.include(ex1.value, 'id: "R34fg663H9KW9MMSKISIhTs1dR7Hss7e"', 'example #1 is type defined example')
    assert.include(ex2.value, 'id: "R34fg663H9KW9MMSKISI"', 'example #2 is payload defined example (raml)')

    assert.include(ex2.sourceMaps!.trackedElement!.value, shape['@id'], 'example #2 has tracked value')
  })

  test('returns a RAML example for the XML mime', async ({ assert }) => {
    const shape = loader.lookupRequestPayload(api, '/body-tracking', 'get', xmlMime)
    const result = serializer.payload(shape)

    const { examples } = result.schema as IApiNodeShape

    assert.lengthOf(examples, 2, 'has both examples from the type and the payload')
    const [ex1, ex2] = examples

    assert.include(ex1.value, 'id: "R34fg663H9KW9MMSKISIhTs1dR7Hss7e"', 'example #1 is type defined example')
    assert.include(ex2.value, 'id: "R34fg663H9KW9MMSKISI"', 'example #2 is payload defined example (raml)')

    assert.include(ex2.sourceMaps!.trackedElement!.value, shape['@id'], 'example #2 has tracked value')
  })

  test('returns a JSON example for the JSON mime', async ({ assert }) => {
    const shape = loader.lookupRequestPayload(api, '/body-tracking', 'put', jsonMime)
    const result = serializer.payload(shape)

    const { examples } = result.schema as IApiNodeShape

    assert.lengthOf(examples, 2, 'has both examples from the type and the payload')
    const [ex1, ex2] = examples
    assert.include(ex1.value, 'id: "R34fg663H9KW9MMSKISIhTs1dR7Hss7e"', 'example #1 is type defined example')
    assert.include(ex2.value, '"id": "R34fg663H9KW9MMSKISI"', 'example #2 is payload defined example (json)')

    assert.include(ex2.sourceMaps!.trackedElement!.value, shape['@id'], 'example #2 has tracked value')
  })

  test('returns a XML example for the XML mime', async ({ assert }) => {
    const shape = loader.lookupRequestPayload(api, '/body-tracking', 'put', xmlMime)
    const result = serializer.payload(shape)

    const { examples } = result.schema as IApiNodeShape

    assert.lengthOf(examples, 2, 'has both examples from the type and the payload')
    const [ex1, ex2] = examples
    assert.include(ex1.value, 'id: "R34fg663H9KW9MMSKISIhTs1dR7Hss7e"', 'example #1 is type defined example')
    assert.include(
      ex2.value,
      '<id>Qawer63J73HJ6khjswuqyq62382jG21s</id>',
      'example #2 is payload defined example (xml)'
    )

    assert.include(ex2.sourceMaps!.trackedElement!.value, shape['@id'], 'example #2 has tracked value')
  })

  test('reuses the same JSON example for the JSON mime', async ({ assert }) => {
    const shape = loader.lookupRequestPayload(api, '/body-tracking', 'post', jsonMime)
    const result = serializer.payload(shape)

    const { examples } = result.schema as IApiNodeShape

    assert.lengthOf(examples, 2, 'has both examples from the type and the payload')
    const [ex1, ex2] = examples
    assert.include(ex1.value, 'id: "R34fg663H9KW9MMSKISIhTs1dR7Hss7e"', 'example #1 is type defined example')
    assert.include(ex2.value, '"id": "R34fg663H9KW9MMSKISI"', 'example #2 is payload defined example (json)')

    assert.include(ex2.sourceMaps!.trackedElement!.value, shape['@id'], 'example #2 has tracked value')
  })

  test('reuses the same XML example for the XML mime', async ({ assert }) => {
    const shape = loader.lookupRequestPayload(api, '/body-tracking', 'post', xmlMime)
    const result = serializer.payload(shape)

    const { examples } = result.schema as IApiNodeShape

    assert.lengthOf(examples, 2, 'has both examples from the type and the payload')
    const [ex1, ex2] = examples
    assert.include(ex1.value, 'id: "R34fg663H9KW9MMSKISIhTs1dR7Hss7e"', 'example #1 is type defined example')
    assert.include(
      ex2.value,
      '<id>Qawer63J73HJ6khjswuqyq62382jG21s</id>',
      'example #2 is payload defined example (xml)'
    )

    assert.include(ex2.sourceMaps!.trackedElement!.value, shape['@id'], 'example #2 has tracked value')
  })

  test('works when a single mime is used', async ({ assert }) => {
    const shape = loader.lookupRequestPayload(api, '/body-tracking', 'delete', jsonMime)
    const result = serializer.payload(shape)

    const { examples } = result.schema as IApiNodeShape

    assert.lengthOf(examples, 2, 'has both examples from the type and the payload')
    const [ex1, ex2] = examples
    assert.include(ex1.value, 'id: "R34fg663H9KW9MMSKISIhTs1dR7Hss7e"', 'example #1 is type defined example')
    assert.include(ex2.value, '"id": "R34fg663H9KW9MMSKISI"', 'example #2 is payload defined example (json)')

    assert.include(ex2.sourceMaps!.trackedElement!.value, shape['@id'], 'example #2 has tracked value')
  })

  test('serializes type only example when no payload example', async ({ assert }) => {
    const shape = loader.lookupRequestPayload(api, '/body-tracking', 'patch', jsonMime)
    const result = serializer.payload(shape)

    const { examples } = result.schema as IApiNodeShape

    assert.lengthOf(examples, 1, 'has only the type example')
    const [ex1] = examples
    assert.include(ex1.value, 'id: "R34fg663H9KW9MMSKISIhTs1dR7Hss7e"', 'example #1 is type defined example')
  })

  test('adds example without tracking information', async ({ assert }) => {
    const shape = loader.lookupRequestPayload(api, '/not-shared', 'post', jsonMime)
    const result = serializer.payload(shape)

    const { examples } = result.schema as IApiNodeShape

    assert.lengthOf(examples, 1, 'has only the payload example')
    const [ex1] = examples
    assert.include(ex1.value, 'id: 1234567890', 'example #1 is type defined example')
  })
})
