import type { PluginInstallationItemResponse } from '@dify/contracts/api/console/workspaces/types.gen'
import type { ReactNode } from 'react'
import type { Permissions, PluginTaskStart } from '@/app/components/plugins/types'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { act, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { FormTypeEnum } from '@/app/components/base/form/types'
import {
  AUTO_UPDATE_MODE,
  AUTO_UPDATE_STRATEGY,
} from '@/app/components/plugins/reference-setting-modal/auto-update-setting/types'
import {
  PermissionType,
  PluginCategoryEnum,
  PluginSource,
  TaskStatus,
} from '@/app/components/plugins/types'
import { renderHook } from '@/test/console/render'
import {
  normalizeInstalledPluginDetail,
  useInstalledPluginList,
  useMutationPluginAutoUpgradeSettings,
  useMutationPluginPermissionSettings,
  usePluginAutoUpgradeSettings,
  usePluginTaskList,
} from '../use-plugins'

const { mockGet, mockPost } = vi.hoisted(() => ({
  mockGet: vi.fn(),
  mockPost: vi.fn(),
}))

vi.mock('@/service/base', () => ({
  get: mockGet,
  getMarketplace: vi.fn(),
  post: mockPost,
  postMarketplace: vi.fn(),
}))

vi.mock('@/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list', () => ({
  default: () => ({
    refreshPluginList: vi.fn(),
  }),
}))

vi.mock('@/context/permission-state', async () => {
  const { createPermissionStateModuleMock } = await import('@/test/console/state-fixture')

  return createPermissionStateModuleMock(() => ({
    workspacePermissionKeys: ['plugin.install'],
  }))
})

vi.mock('../use-tools', () => ({
  useInvalidateAllBuiltInTools: () => vi.fn(),
}))

const createQueryClient = () =>
  new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
      },
      mutations: {
        retry: false,
      },
    },
  })

const createWrapper = (queryClient: QueryClient) => {
  return function Wrapper({ children }: { children: ReactNode }) {
    return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
  }
}

const createPluginInstallation = (): PluginInstallationItemResponse => ({
  id: 'installation-row-id',
  created_at: '2026-06-01T00:00:00Z',
  updated_at: '2026-06-02T00:00:00Z',
  plugin_id: 'langgenius/full-declaration',
  plugin_unique_identifier: 'langgenius/full-declaration:1.0.0@test',
  tenant_id: 'tenant-id',
  endpoints_setups: 1,
  endpoints_active: 1,
  version: '1.0.0',
  source: PluginSource.marketplace,
  runtime_type: 'local',
  checksum: 'checksum',
  meta: {
    repo: 'langgenius/full-declaration',
    version: '1.0.0',
    package: 'full-declaration.difypkg',
  },
  declaration: {
    version: '1.0.0',
    author: 'Dify',
    icon: 'icon.svg',
    icon_dark: 'icon-dark.svg',
    name: 'full-declaration',
    category: PluginCategoryEnum.trigger,
    label: { en_US: 'Full declaration', zh_Hans: 'Full declaration' },
    description: { en_US: 'Full declaration plugin', zh_Hans: 'Full declaration plugin' },
    created_at: '2026-06-01T00:00:00Z',
    resource: {},
    plugins: {},
    verified: true,
    tags: ['automation'],
    meta: {
      version: '1.0.0',
      minimum_dify_version: '1.4.0',
    },
    tool: {
      identity: {
        author: 'Dify',
        name: 'tool-provider',
        description: { en_US: 'Tool provider' },
        icon: 'tool.svg',
        label: { en_US: 'Tool provider' },
        tags: ['tool'],
      },
      credentials_schema: [
        {
          name: 'api_key',
          label: { en_US: 'API key' },
          type: 'secret-input',
          required: true,
          default: 'token',
        },
      ],
    },
    datasource: {
      identity: {
        author: 'Dify',
        name: 'datasource-provider',
        description: { en_US: 'Datasource provider' },
        icon: 'datasource.svg',
        label: { en_US: 'Datasource provider' },
        tags: ['datasource'],
      },
      credentials_schema: [],
    },
    endpoint: {
      settings: [
        {
          name: 'endpoint_secret',
          label: { en_US: 'Endpoint secret' },
          type: 'secret-input',
          required: true,
          default: '',
        },
      ],
      endpoints: [
        {
          path: '/webhook',
          method: 'POST',
          hidden: false,
        },
      ],
    },
    trigger: {
      events: [
        {
          name: 'issue_created',
          identity: {
            author: 'Dify',
            name: 'issue_created',
            label: { en_US: 'Issue created' },
            provider: 'github',
          },
          description: { en_US: 'Issue created event' },
          parameters: [
            {
              name: 'retry_count',
              label: { en_US: 'Retry count' },
              type: 'number',
              default: 0,
              required: false,
              multiple: false,
            },
          ],
          output_schema: {
            type: 'object',
          },
        },
      ],
      identity: {
        author: 'Dify',
        name: 'github-trigger',
        label: { en_US: 'GitHub trigger' },
        description: { en_US: 'GitHub trigger provider' },
        icon: 'trigger.svg',
        tags: ['trigger'],
      },
      subscription_constructor: {
        credentials_schema: [],
        oauth_schema: {
          client_schema: [],
          credentials_schema: [],
        },
        parameters: [
          {
            name: 'max_retries',
            label: { en_US: 'Max retries' },
            type: 'number',
            default: 3,
            required: false,
            multiple: false,
          },
        ],
      },
      subscription_schema: [
        {
          name: 'repository',
          label: { en_US: 'Repository' },
          type: 'text-input',
          required: true,
        },
      ],
    },
  },
})

describe('normalizeInstalledPluginDetail', () => {
  it('should preserve generated plugin declaration capabilities', () => {
    const detail = normalizeInstalledPluginDetail(createPluginInstallation())

    expect(detail.name).toBe('full-declaration')
    expect(detail.installation_id).toBe('installation-row-id')
    expect(detail.latest_version).toBe('1.0.0')
    expect(detail.latest_unique_identifier).toBe('langgenius/full-declaration:1.0.0@test')
    expect(detail.status).toBe('active')
    expect(detail.declaration.tool?.identity.name).toBe('tool-provider')
    expect(detail.declaration.tool?.credentials_schema[0]?.name).toBe('api_key')
    expect(detail.declaration.datasource?.identity.name).toBe('datasource-provider')
    expect(detail.declaration.endpoint?.endpoints?.[0]).toEqual({
      path: '/webhook',
      method: 'POST',
      hidden: false,
    })
    expect(detail.declaration.trigger.identity.name).toBe('github-trigger')
    expect(detail.declaration.trigger.events[0]?.parameters[0]?.default).toBe(0)
    expect(detail.declaration.trigger.subscription_constructor.parameters[0]?.type).toBe(
      FormTypeEnum.textNumber,
    )
    expect(detail.declaration.trigger.subscription_schema[0]?.name).toBe('repository')
  })
})

describe('use-plugins mutations', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('optimistically updates category auto-upgrade cache before the request finishes', async () => {
    const queryClient = createQueryClient()
    const queryKey = ['plugins', 'referenceSettings', 'autoUpgrade', PluginCategoryEnum.model]
    const previousAutoUpgrade = {
      strategy_setting: AUTO_UPDATE_STRATEGY.latest,
      upgrade_time_of_day: 0,
      upgrade_mode: AUTO_UPDATE_MODE.exclude,
      exclude_plugins: [],
      include_plugins: [],
    }
    const nextAutoUpgrade = {
      ...previousAutoUpgrade,
      upgrade_time_of_day: 3600,
    }
    let resolvePost: (value: unknown) => void = () => {}
    mockPost.mockReturnValue(
      new Promise((resolve) => {
        resolvePost = resolve
      }),
    )
    queryClient.setQueryData(queryKey, {
      category: PluginCategoryEnum.model,
      auto_upgrade: previousAutoUpgrade,
    })

    const { result } = renderHook(
      () => useMutationPluginAutoUpgradeSettings({ category: PluginCategoryEnum.model }),
      { wrapper: createWrapper(queryClient) },
    )

    act(() => {
      result.current.mutate(nextAutoUpgrade)
    })

    await waitFor(() => {
      expect(mockPost).toHaveBeenCalledWith('/workspaces/current/plugin/auto-upgrade/change', {
        body: {
          category: PluginCategoryEnum.model,
          auto_upgrade: nextAutoUpgrade,
        },
      })
    })
    await waitFor(() => {
      expect(queryClient.getQueryData(queryKey)).toEqual({
        category: PluginCategoryEnum.model,
        auto_upgrade: nextAutoUpgrade,
      })
    })

    resolvePost({})
  })

  it('optimistically updates plugin permission cache before the request finishes', async () => {
    const queryClient = createQueryClient()
    const queryKey = ['plugins', 'referenceSettings', 'permission']
    const previousPermission: Permissions = {
      install_permission: PermissionType.admin,
      debug_permission: PermissionType.admin,
    }
    const nextPermission: Permissions = {
      install_permission: PermissionType.everyone,
      debug_permission: PermissionType.admin,
    }
    let resolvePost: (value: unknown) => void = () => {}
    mockPost.mockReturnValue(
      new Promise((resolve) => {
        resolvePost = resolve
      }),
    )
    queryClient.setQueryData(queryKey, previousPermission)

    const { result } = renderHook(() => useMutationPluginPermissionSettings(), {
      wrapper: createWrapper(queryClient),
    })

    act(() => {
      result.current.mutate(nextPermission)
    })

    await waitFor(() => {
      expect(mockPost).toHaveBeenCalledWith('/workspaces/current/plugin/permission/change', {
        body: nextPermission,
      })
    })
    await waitFor(() => {
      expect(queryClient.getQueryData(queryKey)).toEqual(nextPermission)
    })

    resolvePost({})
  })

  it('rolls back category auto-upgrade cache when the request fails', async () => {
    const queryClient = createQueryClient()
    const queryKey = ['plugins', 'referenceSettings', 'autoUpgrade', PluginCategoryEnum.model]
    const previousAutoUpgrade = {
      strategy_setting: AUTO_UPDATE_STRATEGY.latest,
      upgrade_time_of_day: 0,
      upgrade_mode: AUTO_UPDATE_MODE.exclude,
      exclude_plugins: [],
      include_plugins: [],
    }
    const nextAutoUpgrade = {
      ...previousAutoUpgrade,
      upgrade_time_of_day: 3600,
    }
    let rejectPost: (reason?: unknown) => void = () => {}
    mockPost.mockReturnValue(
      new Promise((_resolve, reject) => {
        rejectPost = reject
      }),
    )
    queryClient.setQueryData(queryKey, {
      category: PluginCategoryEnum.model,
      auto_upgrade: previousAutoUpgrade,
    })

    const { result } = renderHook(
      () => useMutationPluginAutoUpgradeSettings({ category: PluginCategoryEnum.model }),
      { wrapper: createWrapper(queryClient) },
    )

    const mutation = result.current.mutateAsync(nextAutoUpgrade).catch(() => undefined)

    await waitFor(() => {
      expect(queryClient.getQueryData(queryKey)).toEqual({
        category: PluginCategoryEnum.model,
        auto_upgrade: nextAutoUpgrade,
      })
    })

    rejectPost(new Error('auto-upgrade update failed'))

    await waitFor(() => {
      expect(queryClient.getQueryData(queryKey)).toEqual({
        category: PluginCategoryEnum.model,
        auto_upgrade: previousAutoUpgrade,
      })
    })
    await mutation
  })

  it('clears optimistic category auto-upgrade cache when the request fails without previous cache', async () => {
    const queryClient = createQueryClient()
    const queryKey = ['plugins', 'referenceSettings', 'autoUpgrade', PluginCategoryEnum.model]
    const nextAutoUpgrade = {
      strategy_setting: AUTO_UPDATE_STRATEGY.latest,
      upgrade_time_of_day: 3600,
      upgrade_mode: AUTO_UPDATE_MODE.exclude,
      exclude_plugins: [],
      include_plugins: [],
    }
    let rejectPost: (reason?: unknown) => void = () => {}
    mockPost.mockReturnValue(
      new Promise((_resolve, reject) => {
        rejectPost = reject
      }),
    )

    const { result } = renderHook(
      () => useMutationPluginAutoUpgradeSettings({ category: PluginCategoryEnum.model }),
      { wrapper: createWrapper(queryClient) },
    )

    const mutation = result.current.mutateAsync(nextAutoUpgrade).catch(() => undefined)

    await waitFor(() => {
      expect(queryClient.getQueryData(queryKey)).toEqual({
        category: PluginCategoryEnum.model,
        auto_upgrade: nextAutoUpgrade,
      })
    })

    rejectPost(new Error('auto-upgrade update failed'))

    await waitFor(() => {
      expect(queryClient.getQueryData(queryKey)).toBeUndefined()
    })
    await mutation
  })

  it('rolls back plugin permission cache when the request fails', async () => {
    const queryClient = createQueryClient()
    const queryKey = ['plugins', 'referenceSettings', 'permission']
    const previousPermission: Permissions = {
      install_permission: PermissionType.admin,
      debug_permission: PermissionType.admin,
    }
    const nextPermission: Permissions = {
      install_permission: PermissionType.everyone,
      debug_permission: PermissionType.admin,
    }
    let rejectPost: (reason?: unknown) => void = () => {}
    mockPost.mockReturnValue(
      new Promise((_resolve, reject) => {
        rejectPost = reject
      }),
    )
    queryClient.setQueryData(queryKey, previousPermission)

    const { result } = renderHook(() => useMutationPluginPermissionSettings(), {
      wrapper: createWrapper(queryClient),
    })

    const mutation = result.current.mutateAsync(nextPermission).catch(() => undefined)

    await waitFor(() => {
      expect(queryClient.getQueryData(queryKey)).toEqual(nextPermission)
    })

    rejectPost(new Error('permission update failed'))

    await waitFor(() => {
      expect(queryClient.getQueryData(queryKey)).toEqual(previousPermission)
    })
    await mutation
  })
})

describe('useInstalledPluginList', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('fetches the default installed plugin list when no category is provided', async () => {
    const queryClient = createQueryClient()
    mockGet.mockResolvedValue({ plugins: [], total: 0 })

    renderHook(() => useInstalledPluginList(false, 100), { wrapper: createWrapper(queryClient) })

    await waitFor(() => {
      expect(mockGet).toHaveBeenCalledWith('/workspaces/current/plugin/list?page=1&page_size=100')
    })
  })

  it('fetches the scoped installed plugin category list when category is provided', async () => {
    const queryClient = createQueryClient()
    mockGet.mockResolvedValue({ plugins: [], has_more: false })

    renderHook(() => useInstalledPluginList(false, 100, { category: PluginCategoryEnum.trigger }), {
      wrapper: createWrapper(queryClient),
    })

    await waitFor(() => {
      expect(mockGet).toHaveBeenCalledWith(
        '/workspaces/current/plugin/trigger/list?page=1&page_size=100',
      )
    })
  })

  it('keeps builtin tools from the scoped tool plugin category response', async () => {
    const queryClient = createQueryClient()
    const builtinTools = [
      {
        id: 'builtin-tool',
        name: 'builtin-tool',
        label: { en_US: 'Builtin Tool', zh_Hans: 'Builtin Tool' },
        description: { en_US: 'Builtin Tool description', zh_Hans: 'Builtin Tool description' },
        author: 'Dify',
        icon: '',
        type: 'builtin',
        team_credentials: {},
        is_team_authorization: false,
        allow_delete: false,
        labels: [],
      },
    ]
    mockGet.mockResolvedValue({ plugins: [], builtin_tools: builtinTools, has_more: false })

    const { result } = renderHook(
      () => useInstalledPluginList(false, 100, { category: PluginCategoryEnum.tool }),
      { wrapper: createWrapper(queryClient) },
    )

    await waitFor(() => {
      expect(result.current.data?.builtin_tools).toEqual(builtinTools)
    })
  })

  it('uses has_more to load the next scoped plugin category page', async () => {
    const queryClient = createQueryClient()
    mockGet
      .mockResolvedValueOnce({
        plugins: [{ plugin_id: 'trigger-plugin-1' }],
        has_more: true,
      })
      .mockResolvedValueOnce({
        plugins: [{ plugin_id: 'trigger-plugin-2' }],
        has_more: false,
      })

    const { result } = renderHook(
      () => useInstalledPluginList(false, 100, { category: PluginCategoryEnum.trigger }),
      { wrapper: createWrapper(queryClient) },
    )

    await waitFor(() => {
      expect(result.current.isLastPage).toBe(false)
    })

    act(() => {
      result.current.loadNextPage()
    })

    await waitFor(() => {
      expect(mockGet).toHaveBeenCalledWith(
        '/workspaces/current/plugin/trigger/list?page=2&page_size=100',
      )
    })
    await waitFor(() => {
      expect(result.current.isLastPage).toBe(true)
    })
  })

  it('keeps builtin tools from the first scoped tool plugin page when loading more pages', async () => {
    const queryClient = createQueryClient()
    const builtinTools = [
      {
        id: 'builtin-tool',
        name: 'builtin-tool',
        label: { en_US: 'Builtin Tool', zh_Hans: 'Builtin Tool' },
        description: { en_US: 'Builtin Tool description', zh_Hans: 'Builtin Tool description' },
        author: 'Dify',
        icon: '',
        type: 'builtin',
        team_credentials: {},
        is_team_authorization: false,
        allow_delete: false,
        labels: [],
      },
    ]
    mockGet
      .mockResolvedValueOnce({
        plugins: [{ plugin_id: 'tool-plugin-1' }],
        builtin_tools: builtinTools,
        has_more: true,
      })
      .mockResolvedValueOnce({
        plugins: [{ plugin_id: 'tool-plugin-2' }],
        builtin_tools: builtinTools,
        has_more: false,
      })

    const { result } = renderHook(
      () => useInstalledPluginList(false, 100, { category: PluginCategoryEnum.tool }),
      { wrapper: createWrapper(queryClient) },
    )

    await waitFor(() => {
      expect(result.current.isLastPage).toBe(false)
    })

    act(() => {
      result.current.loadNextPage()
    })

    await waitFor(() => {
      expect(result.current.data?.plugins).toEqual([
        { plugin_id: 'tool-plugin-1' },
        { plugin_id: 'tool-plugin-2' },
      ])
    })
    expect(result.current.data?.builtin_tools).toEqual(builtinTools)
  })
})

describe('usePluginTaskList', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('adds the task from an install start response to the task list cache', async () => {
    const queryClient = createQueryClient()
    queryClient.setQueryData(['plugins', 'referenceSettings', 'permission'], {
      install_permission: PermissionType.admin,
      debug_permission: PermissionType.admin,
    })
    mockGet.mockResolvedValue({ tasks: [] })

    const startedTask: PluginTaskStart = {
      id: 'task-new',
      created_at: '2026-06-05T03:34:59.578653Z',
      updated_at: '2026-06-05T03:34:59.578653Z',
      status: 'running',
      total_plugins: 1,
      completed_plugins: 0,
      plugins: [
        {
          plugin_unique_identifier: 'langgenius/gitlab_datasource:0.3.11@test',
          plugin_id: 'langgenius/gitlab_datasource',
          status: TaskStatus.running,
          message: '',
          icon: 'gitlab.png',
          labels: {
            en_US: 'GitLab',
          } as PluginTaskStart['plugins'][number]['labels'],
          source: PluginSource.marketplace,
        },
      ],
    }

    const { result } = renderHook(() => usePluginTaskList(PluginCategoryEnum.tool), {
      wrapper: createWrapper(queryClient),
    })

    act(() => {
      result.current.handleInstallTaskStart({
        all_installed: false,
        task_id: 'task-new',
        plugin_unique_identifier: 'langgenius/gitlab_datasource:0.3.11@test',
        task: startedTask,
      })
    })

    expect(queryClient.getQueryData(['plugins', 'pluginTaskList'])).toEqual({
      tasks: [
        {
          ...startedTask,
          plugins: [
            {
              ...startedTask.plugins[0],
              taskId: 'task-new',
            },
          ],
        },
      ],
    })
  })

  it('replaces an existing task with the latest start response task data', () => {
    const queryClient = createQueryClient()
    queryClient.setQueryData(['plugins', 'referenceSettings', 'permission'], {
      install_permission: PermissionType.admin,
      debug_permission: PermissionType.admin,
    })
    queryClient.setQueryData(['plugins', 'pluginTaskList'], {
      tasks: [
        {
          id: 'task-new',
          created_at: '2026-06-05T03:34:59.578653Z',
          updated_at: '2026-06-05T03:34:59.578653Z',
          status: 'running',
          total_plugins: 1,
          completed_plugins: 0,
          plugins: [],
        },
        {
          id: 'task-old',
          created_at: '2026-06-04T03:34:59.578653Z',
          updated_at: '2026-06-04T03:34:59.578653Z',
          status: 'success',
          total_plugins: 1,
          completed_plugins: 1,
          plugins: [],
        },
      ],
    })
    mockGet.mockResolvedValue({ tasks: [] })

    const { result } = renderHook(() => usePluginTaskList(PluginCategoryEnum.tool), {
      wrapper: createWrapper(queryClient),
    })

    act(() => {
      result.current.handleInstallTaskStart({
        all_installed: false,
        task_id: 'task-new',
        plugin_unique_identifier: 'langgenius/gitlab_datasource:0.3.11@test',
        task: {
          id: 'task-new',
          created_at: '2026-06-05T03:34:59.578653Z',
          updated_at: '2026-06-05T03:35:59.578653Z',
          status: 'success',
          total_plugins: 1,
          completed_plugins: 1,
          plugins: [],
        },
      })
    })

    expect(queryClient.getQueryData(['plugins', 'pluginTaskList'])).toEqual({
      tasks: [
        {
          id: 'task-new',
          created_at: '2026-06-05T03:34:59.578653Z',
          updated_at: '2026-06-05T03:35:59.578653Z',
          status: 'success',
          total_plugins: 1,
          completed_plugins: 1,
          plugins: [],
        },
        {
          id: 'task-old',
          created_at: '2026-06-04T03:34:59.578653Z',
          updated_at: '2026-06-04T03:34:59.578653Z',
          status: 'success',
          total_plugins: 1,
          completed_plugins: 1,
          plugins: [],
        },
      ],
    })
  })

  it('keeps a locally started unfinished task when an immediate refetch returns a stale task list', async () => {
    const queryClient = createQueryClient()
    queryClient.setQueryData(['plugins', 'referenceSettings', 'permission'], {
      install_permission: PermissionType.admin,
      debug_permission: PermissionType.admin,
    })
    const staleTask = {
      id: 'task-old',
      created_at: '2026-06-04T03:34:59.578653Z',
      updated_at: '2026-06-04T03:34:59.578653Z',
      status: TaskStatus.success,
      total_plugins: 1,
      completed_plugins: 1,
      plugins: [],
    }
    mockGet.mockResolvedValue({ tasks: [staleTask] })
    const startedTask: PluginTaskStart = {
      id: 'task-new',
      created_at: '2026-06-05T03:34:59.578653Z',
      updated_at: '2026-06-05T03:34:59.578653Z',
      status: TaskStatus.running,
      total_plugins: 1,
      completed_plugins: 0,
      plugins: [
        {
          plugin_unique_identifier: 'langgenius/gitlab_datasource:0.3.11@test',
          plugin_id: 'langgenius/gitlab_datasource',
          status: TaskStatus.pending,
          message: '',
          icon: 'gitlab.png',
          labels: {
            en_US: 'GitLab',
          } as PluginTaskStart['plugins'][number]['labels'],
          source: PluginSource.marketplace,
        },
      ],
    }

    const { result } = renderHook(() => usePluginTaskList(PluginCategoryEnum.tool), {
      wrapper: createWrapper(queryClient),
    })

    await waitFor(() => {
      expect(queryClient.getQueryData(['plugins', 'pluginTaskList'])).toEqual({
        tasks: [staleTask],
      })
    })

    act(() => {
      result.current.handleInstallTaskStart({
        all_installed: false,
        task_id: 'task-new',
        task: startedTask,
      })
    })

    await waitFor(() => {
      expect(queryClient.getQueryData(['plugins', 'pluginTaskList'])).toEqual({
        tasks: [
          {
            ...startedTask,
            plugins: [
              {
                ...startedTask.plugins[0],
                taskId: 'task-new',
              },
            ],
          },
          staleTask,
        ],
      })
    })
  })
})

describe('usePluginAutoUpgradeSettings', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('does not expose frontend default settings before backend data resolves', () => {
    const queryClient = createQueryClient()
    mockGet.mockReturnValue(new Promise(() => {}))

    const { result } = renderHook(() => usePluginAutoUpgradeSettings(PluginCategoryEnum.model), {
      wrapper: createWrapper(queryClient),
    })

    expect(result.current.data).toBeUndefined()
    expect(mockGet).toHaveBeenCalledWith('/workspaces/current/plugin/auto-upgrade/fetch', {
      params: {
        category: PluginCategoryEnum.model,
      },
    })
  })

  it('returns backend auto-upgrade settings when the request resolves', async () => {
    const queryClient = createQueryClient()
    const backendAutoUpgrade = {
      strategy_setting: AUTO_UPDATE_STRATEGY.fixOnly,
      upgrade_time_of_day: 0,
      upgrade_mode: AUTO_UPDATE_MODE.exclude,
      exclude_plugins: [],
      include_plugins: [],
    }
    mockGet.mockResolvedValue({
      category: PluginCategoryEnum.tool,
      auto_upgrade: backendAutoUpgrade,
    })

    const { result } = renderHook(() => usePluginAutoUpgradeSettings(PluginCategoryEnum.tool), {
      wrapper: createWrapper(queryClient),
    })

    await waitFor(() => {
      expect(result.current.data).toEqual({
        category: PluginCategoryEnum.tool,
        auto_upgrade: backendAutoUpgrade,
      })
    })
  })
})
