import type { PluginDetail } from '@/app/components/plugins/types'
import { fireEvent, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { renderWithConsoleQuery as render } from '@/test/console/query-data'
import EndpointList from '../endpoint-list'

vi.mock('@langgenius/dify-ui/cn', () => ({
  cn: (...args: (string | undefined | false | null)[]) => args.filter(Boolean).join(' '),
}))

const mockEndpoints = [
  {
    id: 'ep-1',
    name: 'Endpoint 1',
    url: 'https://api.example.com',
    declaration: { settings: [], endpoints: [] },
  },
]

let mockEndpointListData: { endpoints: typeof mockEndpoints } | undefined

const mockInvalidateEndpointList = vi.fn()
const mockInvalidateInstalledPluginList = vi.fn()
const mockCreateEndpoint = vi.fn()

vi.mock('@/service/use-endpoints', () => ({
  useEndpointList: () => ({ data: mockEndpointListData }),
  useInvalidateEndpointList: () => mockInvalidateEndpointList,
  useCreateEndpoint: ({ onSuccess }: { onSuccess: () => void }) => ({
    mutate: (data: unknown) => {
      mockCreateEndpoint(data)
      onSuccess()
    },
  }),
}))

vi.mock('@/service/use-plugins', () => ({
  useInvalidateInstalledPluginList: () => mockInvalidateInstalledPluginList,
}))

vi.mock('@/app/components/tools/utils/to-form-schema', () => ({
  toolCredentialToFormSchemas: (schemas: unknown[]) => schemas,
}))

vi.mock('../endpoint-card', () => ({
  default: ({ data }: { data: { name: string } }) => (
    <div data-testid="endpoint-card">{data.name}</div>
  ),
}))

vi.mock('../endpoint-modal', () => ({
  default: ({ onCancel, onSaved }: { onCancel: () => void; onSaved: (state: unknown) => void }) => (
    <div data-testid="endpoint-modal">
      <button data-testid="modal-cancel" onClick={onCancel}>
        Cancel
      </button>
      <button data-testid="modal-save" onClick={() => onSaved({ name: 'New Endpoint' })}>
        Save
      </button>
    </div>
  ),
}))

const createPluginDetail = (): PluginDetail => ({
  id: 'test-id',
  created_at: '2024-01-01',
  updated_at: '2024-01-02',
  name: 'Test Plugin',
  plugin_id: 'test-plugin',
  plugin_unique_identifier: 'test-uid',
  declaration: {
    endpoint: { settings: [], endpoints: [] },
    tool: undefined,
  } as unknown as PluginDetail['declaration'],
  installation_id: 'install-1',
  tenant_id: 'tenant-1',
  endpoints_setups: 0,
  endpoints_active: 0,
  version: '1.0.0',
  latest_version: '1.0.0',
  latest_unique_identifier: 'test-uid',
  source: 'marketplace' as PluginDetail['source'],
  meta: undefined,
  status: 'active',
  deprecated_reason: '',
  alternative_plugin_id: '',
})

describe('EndpointList', () => {
  const getAddButton = () =>
    screen.getByRole('button', { name: 'plugin.detailPanel.endpointModalTitle' })

  beforeEach(() => {
    vi.clearAllMocks()
    mockEndpointListData = { endpoints: mockEndpoints }
  })

  describe('Rendering', () => {
    it('should render endpoint list', () => {
      render(<EndpointList detail={createPluginDetail()} />)

      expect(screen.getByText('plugin.detailPanel.endpoints'))!.toBeInTheDocument()
    })

    it('should render endpoint cards', () => {
      render(<EndpointList detail={createPluginDetail()} />)

      expect(screen.getByTestId('endpoint-card'))!.toBeInTheDocument()
      expect(screen.getByText('Endpoint 1'))!.toBeInTheDocument()
    })

    it('should return null when no data', () => {
      mockEndpointListData = undefined
      const { container } = render(<EndpointList detail={createPluginDetail()} />)

      expect(container)!.toBeEmptyDOMElement()
    })

    it('should show empty message when no endpoints', () => {
      mockEndpointListData = { endpoints: [] }
      render(<EndpointList detail={createPluginDetail()} />)

      expect(screen.getByText('plugin.detailPanel.endpointsEmpty'))!.toBeInTheDocument()
    })

    it('should render add button', () => {
      render(<EndpointList detail={createPluginDetail()} />)

      expect(getAddButton()).toBeInTheDocument()
    })
  })

  describe('User Interactions', () => {
    it('should show modal when add button clicked', () => {
      render(<EndpointList detail={createPluginDetail()} />)

      fireEvent.click(getAddButton())

      expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument()
    })

    it('should hide modal when cancel clicked', () => {
      render(<EndpointList detail={createPluginDetail()} />)

      fireEvent.click(getAddButton())
      expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument()

      fireEvent.click(screen.getByTestId('modal-cancel'))
      expect(screen.queryByTestId('endpoint-modal')).not.toBeInTheDocument()
    })

    it('should call createEndpoint when save clicked', () => {
      render(<EndpointList detail={createPluginDetail()} />)

      fireEvent.click(getAddButton())
      fireEvent.click(screen.getByTestId('modal-save'))

      expect(mockCreateEndpoint).toHaveBeenCalled()
    })
  })

  describe('Border Style', () => {
    it('should render with border style based on tool existence', () => {
      const detail = createPluginDetail()
      detail.declaration.tool = {} as PluginDetail['declaration']['tool']
      render(<EndpointList detail={detail} />)

      expect(screen.getByText('plugin.detailPanel.endpoints'))!.toBeInTheDocument()
    })
  })

  describe('Multiple Endpoints', () => {
    it('should render multiple endpoint cards', () => {
      mockEndpointListData = {
        endpoints: [
          {
            id: 'ep-1',
            name: 'Endpoint 1',
            url: 'https://api1.example.com',
            declaration: { settings: [], endpoints: [] },
          },
          {
            id: 'ep-2',
            name: 'Endpoint 2',
            url: 'https://api2.example.com',
            declaration: { settings: [], endpoints: [] },
          },
        ],
      }
      render(<EndpointList detail={createPluginDetail()} />)

      expect(screen.getAllByTestId('endpoint-card')).toHaveLength(2)
    })
  })

  describe('Create Endpoint Flow', () => {
    it('should invalidate endpoint list after successful create', () => {
      render(<EndpointList detail={createPluginDetail()} />)

      fireEvent.click(getAddButton())
      fireEvent.click(screen.getByTestId('modal-save'))

      return waitFor(() => {
        expect(mockInvalidateEndpointList).toHaveBeenCalledWith('test-plugin')
        expect(mockInvalidateInstalledPluginList).toHaveBeenCalled()
      })
    })

    it('should pass correct params to createEndpoint', () => {
      render(<EndpointList detail={createPluginDetail()} />)

      fireEvent.click(getAddButton())
      fireEvent.click(screen.getByTestId('modal-save'))

      expect(mockCreateEndpoint).toHaveBeenCalledWith({
        pluginUniqueID: 'test-uid',
        state: { name: 'New Endpoint' },
      })
    })
  })
})
