import React from 'react'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import AddAnnotationModal from './index'
import { useProviderContext } from '@/context/provider-context'

jest.mock('@/context/provider-context', () => ({
  useProviderContext: jest.fn(),
}))

const mockToastNotify = jest.fn()
jest.mock('@/app/components/base/toast', () => ({
  __esModule: true,
  default: {
    notify: jest.fn(args => mockToastNotify(args)),
  },
}))

jest.mock('@/app/components/billing/annotation-full', () => () => <div data-testid="annotation-full" />)

const mockUseProviderContext = useProviderContext as jest.Mock

const getProviderContext = ({ usage = 0, total = 10, enableBilling = false } = {}) => ({
  plan: {
    usage: { annotatedResponse: usage },
    total: { annotatedResponse: total },
  },
  enableBilling,
})

describe('AddAnnotationModal', () => {
  const baseProps = {
    isShow: true,
    onHide: jest.fn(),
    onAdd: jest.fn(),
  }

  beforeEach(() => {
    jest.clearAllMocks()
    mockUseProviderContext.mockReturnValue(getProviderContext())
  })

  const typeQuestion = (value: string) => {
    fireEvent.change(screen.getByPlaceholderText('appAnnotation.addModal.queryPlaceholder'), {
      target: { value },
    })
  }

  const typeAnswer = (value: string) => {
    fireEvent.change(screen.getByPlaceholderText('appAnnotation.addModal.answerPlaceholder'), {
      target: { value },
    })
  }

  test('should render modal title when drawer is visible', () => {
    render(<AddAnnotationModal {...baseProps} />)

    expect(screen.getByText('appAnnotation.addModal.title')).toBeInTheDocument()
  })

  test('should capture query input text when typing', () => {
    render(<AddAnnotationModal {...baseProps} />)
    typeQuestion('Sample question')
    expect(screen.getByPlaceholderText('appAnnotation.addModal.queryPlaceholder')).toHaveValue('Sample question')
  })

  test('should capture answer input text when typing', () => {
    render(<AddAnnotationModal {...baseProps} />)
    typeAnswer('Sample answer')
    expect(screen.getByPlaceholderText('appAnnotation.addModal.answerPlaceholder')).toHaveValue('Sample answer')
  })

  test('should show annotation full notice and disable submit when quota exceeded', () => {
    mockUseProviderContext.mockReturnValue(getProviderContext({ usage: 10, total: 10, enableBilling: true }))
    render(<AddAnnotationModal {...baseProps} />)

    expect(screen.getByTestId('annotation-full')).toBeInTheDocument()
    expect(screen.getByRole('button', { name: 'common.operation.add' })).toBeDisabled()
  })

  test('should call onAdd with form values when create next enabled', async () => {
    const onAdd = jest.fn().mockResolvedValue(undefined)
    render(<AddAnnotationModal {...baseProps} onAdd={onAdd} />)

    typeQuestion('Question value')
    typeAnswer('Answer value')
    fireEvent.click(screen.getByTestId('checkbox-create-next-checkbox'))

    await act(async () => {
      fireEvent.click(screen.getByRole('button', { name: 'common.operation.add' }))
    })

    expect(onAdd).toHaveBeenCalledWith({ question: 'Question value', answer: 'Answer value' })
  })

  test('should reset fields after saving when create next enabled', async () => {
    const onAdd = jest.fn().mockResolvedValue(undefined)
    render(<AddAnnotationModal {...baseProps} onAdd={onAdd} />)

    typeQuestion('Question value')
    typeAnswer('Answer value')
    const createNextToggle = screen.getByText('appAnnotation.addModal.createNext').previousElementSibling as HTMLElement
    fireEvent.click(createNextToggle)

    await act(async () => {
      fireEvent.click(screen.getByRole('button', { name: 'common.operation.add' }))
    })

    await waitFor(() => {
      expect(screen.getByPlaceholderText('appAnnotation.addModal.queryPlaceholder')).toHaveValue('')
      expect(screen.getByPlaceholderText('appAnnotation.addModal.answerPlaceholder')).toHaveValue('')
    })
  })

  test('should show toast when validation fails for missing question', () => {
    render(<AddAnnotationModal {...baseProps} />)

    fireEvent.click(screen.getByRole('button', { name: 'common.operation.add' }))
    expect(mockToastNotify).toHaveBeenCalledWith(expect.objectContaining({
      type: 'error',
      message: 'appAnnotation.errorMessage.queryRequired',
    }))
  })

  test('should show toast when validation fails for missing answer', () => {
    render(<AddAnnotationModal {...baseProps} />)
    typeQuestion('Filled question')
    fireEvent.click(screen.getByRole('button', { name: 'common.operation.add' }))

    expect(mockToastNotify).toHaveBeenCalledWith(expect.objectContaining({
      type: 'error',
      message: 'appAnnotation.errorMessage.answerRequired',
    }))
  })

  test('should close modal when save completes and create next unchecked', async () => {
    const onAdd = jest.fn().mockResolvedValue(undefined)
    render(<AddAnnotationModal {...baseProps} onAdd={onAdd} />)

    typeQuestion('Q')
    typeAnswer('A')

    await act(async () => {
      fireEvent.click(screen.getByRole('button', { name: 'common.operation.add' }))
    })

    expect(baseProps.onHide).toHaveBeenCalled()
  })

  test('should allow cancel button to close the drawer', () => {
    render(<AddAnnotationModal {...baseProps} />)

    fireEvent.click(screen.getByRole('button', { name: 'common.operation.cancel' }))
    expect(baseProps.onHide).toHaveBeenCalled()
  })
})
