import type { Plugin } from '../../../../types'
import type { VersionProps } from '@/app/components/plugins/types'
import { fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import LoadedItem from '../loaded-item'

const mockCard = vi.fn()
const mockVersion = vi.fn()
const mockUsePluginInstallLimit = vi.fn()

vi.mock('@/config', () => ({
  API_PREFIX: 'https://api.example.com',
  MARKETPLACE_API_PREFIX: 'https://marketplace.example.com',
}))

vi.mock('../../../../card', () => ({
  default: (props: { titleLeft?: React.ReactNode }) => {
    mockCard(props)
    return <div data-testid="card">{props.titleLeft}</div>
  },
}))

vi.mock('../../../base/use-get-icon', () => ({
  default: () => ({
    getIconUrl: (icon: string) => `https://api.example.com/${icon}`,
  }),
}))

vi.mock('../../../base/version', () => ({
  default: (props: Record<string, unknown>) => {
    mockVersion(props)
    return <div data-testid="version">version</div>
  },
}))

vi.mock('../../../hooks/use-install-plugin-limit', () => ({
  default: (payload: Plugin) => mockUsePluginInstallLimit(payload),
}))

const payload = {
  plugin_id: 'plugin-1',
  org: 'dify',
  name: 'Loaded Plugin',
  icon: 'icon.png',
  version: '1.0.0',
} as Plugin

const versionInfo: VersionProps = {
  hasInstalled: false,
  installedVersion: '',
  toInstallVersion: '0.9.0',
}

describe('LoadedItem', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockUsePluginInstallLimit.mockReturnValue({ canInstall: true })
  })

  it('uses local icon url and forwards version title for non-marketplace plugins', () => {
    render(
      <LoadedItem checked onCheckedChange={vi.fn()} payload={payload} versionInfo={versionInfo} />,
    )

    expect(screen.getByTestId('card')).toBeInTheDocument()
    expect(mockUsePluginInstallLimit).toHaveBeenCalledWith(payload)
    expect(mockCard).toHaveBeenCalledWith(
      expect.objectContaining({
        limitedInstall: false,
        payload: expect.objectContaining({
          ...payload,
          icon: 'https://api.example.com/icon.png',
        }),
        titleLeft: expect.anything(),
      }),
    )
    expect(mockVersion).toHaveBeenCalledWith(
      expect.objectContaining({
        hasInstalled: false,
        installedVersion: '',
        toInstallVersion: '1.0.0',
      }),
    )
  })

  it('uses marketplace icon url and disables checkbox when install limit is reached', () => {
    mockUsePluginInstallLimit.mockReturnValue({ canInstall: false })

    render(
      <LoadedItem
        checked={false}
        onCheckedChange={vi.fn()}
        payload={payload}
        isFromMarketPlace
        versionInfo={versionInfo}
      />,
    )

    expect(screen.getByRole('checkbox', { name: 'Loaded Plugin' })).toHaveAttribute(
      'aria-disabled',
      'true',
    )
    expect(mockCard).toHaveBeenCalledWith(
      expect.objectContaining({
        limitedInstall: true,
        payload: expect.objectContaining({
          icon: 'https://marketplace.example.com/plugins/dify/Loaded Plugin/icon',
        }),
      }),
    )
  })

  it('calls onCheckedChange with payload when checkbox is toggled', () => {
    const onCheckedChange = vi.fn()

    render(
      <LoadedItem
        checked={false}
        onCheckedChange={onCheckedChange}
        payload={payload}
        versionInfo={versionInfo}
      />,
    )

    fireEvent.click(screen.getByRole('checkbox', { name: 'Loaded Plugin' }))

    expect(onCheckedChange).toHaveBeenCalledWith(payload)
  })

  it('omits version badge when payload has no version', () => {
    render(
      <LoadedItem
        checked={false}
        onCheckedChange={vi.fn()}
        payload={{ ...payload, version: '' }}
        versionInfo={versionInfo}
      />,
    )

    expect(mockCard).toHaveBeenCalledWith(
      expect.objectContaining({
        titleLeft: null,
      }),
    )
  })
})
