import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { Controller, useForm } from 'react-hook-form'

import {
  buildKafkaPrivateEndpointOptions,
  getBootstrapPortsValidationRules,
  isAmazonMskPrivateEndpoint,
  validateKafkaPrivateEndpointValue
} from './kafkaPrivateEndpointOptionHelpers'

describe('buildKafkaPrivateEndpointOptions', () => {
  it('allows an available Amazon MSK endpoint without an advertised listener', () => {
    const options = buildKafkaPrivateEndpointOptions([
      {
        id: 'msk-endpoint',
        endpoint_name: 'Amazon MSK',
        endpoint_type: 'AMAZON_MSK',
        status: 'SINK_ENDPOINT_STATUS_AVAILABLE'
      }
    ])

    expect(options).toEqual([
      {
        label: 'Amazon MSK',
        value: 'msk-endpoint',
        disabled: false,
        disabledReason: ''
      }
    ])
    expect(validateKafkaPrivateEndpointValue('msk-endpoint', options)).toBe(true)
  })

  it('still requires an advertised listener for a regular endpoint', () => {
    const options = buildKafkaPrivateEndpointOptions([
      {
        id: 'regular-endpoint',
        endpoint_name: 'Regular endpoint',
        endpoint_type: 'VPC_ENDPOINT_SERVICE',
        status: 'SINK_ENDPOINT_STATUS_AVAILABLE'
      }
    ])

    expect(options[0]).toMatchObject({
      value: 'regular-endpoint',
      disabled: true
    })
    expect(options[0].disabledReason).toContain('require an advertised listener domain')
  })

  it('still disables an Amazon MSK endpoint that is not available', () => {
    const options = buildKafkaPrivateEndpointOptions([
      {
        id: 'pending-msk-endpoint',
        endpoint_name: 'Pending Amazon MSK',
        endpoint_type: 'AMAZON_MSK',
        status: 'SINK_ENDPOINT_STATUS_PENDING_ACCEPTANCE'
      }
    ])

    expect(options[0]).toMatchObject({
      value: 'pending-msk-endpoint',
      disabled: true
    })
    expect(options[0].disabledReason).toContain('Pending Acceptance')
    expect(options[0].disabledReason).not.toContain('advertised listener')
  })
})

describe('isAmazonMskPrivateEndpoint', () => {
  it('matches an Amazon MSK endpoint by its selected value', () => {
    expect(
      isAmazonMskPrivateEndpoint(
        [
          {
            endpoint_id: 'msk-endpoint',
            endpoint_type: 'AMAZON_MSK'
          }
        ],
        'msk-endpoint'
      )
    ).toBe(true)
  })

  it('does not match a regular endpoint', () => {
    expect(
      isAmazonMskPrivateEndpoint(
        [
          {
            id: 'regular-endpoint',
            endpoint_type: 'VPC_ENDPOINT_SERVICE'
          }
        ],
        'regular-endpoint'
      )
    ).toBe(false)
  })
})

describe('getBootstrapPortsValidationRules', () => {
  it('removes the existing required validation after selecting an Amazon MSK endpoint', async () => {
    const onSubmit = jest.fn()

    function TestForm({ isAmazonMskEndpoint }: { isAmazonMskEndpoint: boolean }) {
      const { control, handleSubmit } = useForm<{ ports: string }>({ defaultValues: { ports: '' } })

      return (
        <form onSubmit={handleSubmit(onSubmit)}>
          <Controller
            control={control}
            name="ports"
            rules={getBootstrapPortsValidationRules(isAmazonMskEndpoint)}
            render={({ field, fieldState }) => (
              <>
                <input aria-label="Bootstrap Ports" {...field} />
                {fieldState.error?.message && <span>{fieldState.error.message}</span>}
              </>
            )}
          />
          <button type="submit">Next</button>
        </form>
      )
    }

    const { rerender } = render(<TestForm isAmazonMskEndpoint={false} />)

    fireEvent.click(screen.getByRole('button', { name: 'Next' }))
    expect(await screen.findByText('Required')).not.toBeNull()

    rerender(<TestForm isAmazonMskEndpoint />)
    fireEvent.click(screen.getByRole('button', { name: 'Next' }))

    await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1))
    expect(screen.queryByText('Required')).toBeNull()
  })
})
