import { describe, expect, it, vi } from 'vitest'
import { renderHook, act, waitFor } from '@testing-library/react'
import { FieldsProvider } from './provider.js'
import { useFieldValues, useEntityFields, useFieldGroupBuilder } from './hooks.js'
import type { FieldsClient } from './client.js'

const ref = { entityType: 'content', entityId: 'c1' }
const wrap = (client: FieldsClient) =>
  function Wrapper({ children }: { children: React.ReactNode }) {
    return <FieldsProvider client={client}>{children}</FieldsProvider>
  }

describe('useFieldValues SEO seed', () => {
  it('does NOT fetch on mount when initialData present', () => {
    const getEntityValues = vi.fn()
    const client = { getEntityValues } as unknown as FieldsClient
    const { result } = renderHook(() => useFieldValues(ref, { initialData: { material: 'leather' } }), {
      wrapper: wrap(client),
    })
    expect(getEntityValues).not.toHaveBeenCalled()
    expect(result.current.values).toEqual({ material: 'leather' })
    expect(result.current.loading).toBe(false)
  })
  it('fetches on mount when no seed', async () => {
    const getEntityValues = vi.fn(async () => ({ material: 'suede' }))
    const client = { getEntityValues } as unknown as FieldsClient
    const { result } = renderHook(() => useFieldValues(ref, {}), { wrapper: wrap(client) })
    await waitFor(() => expect(result.current.loading).toBe(false))
    expect(getEntityValues).toHaveBeenCalledTimes(1)
    expect(result.current.values).toEqual({ material: 'suede' })
  })
})

describe('useEntityFields edit lifecycle', () => {
  it('save calls setEntityValues', async () => {
    const setEntityValues = vi.fn(async () => {})
    const client = {
      getEntityValues: async () => ({}),
      resolveGroups: async () => [],
      setEntityValues,
    } as unknown as FieldsClient
    const { result } = renderHook(() => useEntityFields(ref, { initialData: {} }), { wrapper: wrap(client) })
    await act(async () => {
      await result.current.save('g', { material: 'leather' })
    })
    expect(setEntityValues).toHaveBeenCalledWith({ ref, groupId: 'g', values: { material: 'leather' } })
  })
})

describe('useFieldGroupBuilder', () => {
  it('create delegates to client and refreshes list', async () => {
    const created = {
      key: 'k',
      label: 'L',
      location: { entityType: 'content' },
      fields: [],
      origin: 'db' as const,
      id: '1',
    }
    const listGroups = vi.fn(async () => [created])
    const client = {
      listGroups,
      createGroup: vi.fn(async () => created),
      updateGroup: vi.fn(),
      deleteGroup: vi.fn(),
    } as unknown as FieldsClient
    const { result } = renderHook(() => useFieldGroupBuilder('content', {}), { wrapper: wrap(client) })
    await waitFor(() => expect(result.current.groups.length).toBe(1))
  })
})
