// @vitest-environment happy-dom
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'

const cmsApiMock = vi.fn()
vi.mock('../../lib/api.js', () => ({
  cmsApi: (...args: unknown[]) => cmsApiMock(...args),
}))

const { PostTypeEditor } = await import('../../views/Posts/PostTypeEditor.js')

const COLLECTIONS = [
  {
    slug: 'blog',
    labels: { singular: 'Blog Post', plural: 'Blog' },
    type: 'post',
    urlPrefix: 'blog',
    description: 'Long-form articles',
    icon: 'file-text',
    color: 'purple',
    group: 'Posts',
    hidden: false,
    fieldCount: 3,
    fields: [
      { name: 'title', type: 'text', required: true },
      { name: 'body', type: 'richText', required: false },
      { name: 'featuredImage', type: 'media', required: false },
    ],
  },
]

const POSTS = {
  posts: [],
  total: 7,
  page: 1,
  pageSize: 1,
  types: [
    {
      slug: 'blog',
      singular: 'Blog Post',
      plural: 'Blog',
      description: 'Long-form articles',
      urlPrefix: 'blog',
      color: 'purple',
      icon: 'file-text',
      fieldCount: 3,
      count: 7,
    },
  ],
  authors: [],
}

function installMocks() {
  cmsApiMock.mockImplementation((url: string) => {
    if (url === '/collections') return { data: COLLECTIONS }
    if (url.startsWith('/posts')) return { data: POSTS }
    return { error: `unexpected url: ${url}` }
  })
}

describe('PostTypeEditor', () => {
  beforeEach(() => {
    cmsApiMock.mockReset()
    installMocks()
  })

  it('renders identity, post-count badge, and the live field list', async () => {
    render(<PostTypeEditor slug="blog" onNavigate={vi.fn()} />)

    await waitFor(() => expect(screen.getByText('Field Builder')).toBeTruthy())

    // Toolbar: breadcrumb + count badge.
    expect(screen.getByRole('navigation', { name: 'Breadcrumb' }).textContent).toContain('Blog')
    expect(screen.getByText('7 posts')).toBeTruthy()

    // Identity panel values.
    expect(screen.getByText('Long-form articles')).toBeTruthy()
    expect(screen.getByText('/api/cms/collections/blog/{id}')).toBeTruthy()

    // Field rows with humanized labels, keys, and type badges.
    expect(screen.getByText('Featured Image')).toBeTruthy()
    expect(screen.getByText('featuredImage')).toBeTruthy()
    expect(screen.getByText('Rich Text')).toBeTruthy()
    expect(screen.getByText('Required')).toBeTruthy()
    expect(screen.getAllByText('Optional')).toHaveLength(2)
  })

  it('generates a copyable field snippet and flags duplicate keys', async () => {
    render(<PostTypeEditor slug="blog" onNavigate={vi.fn()} />)
    await waitFor(() => expect(screen.getByText('Field Builder')).toBeTruthy())

    fireEvent.click(screen.getByRole('button', { name: 'Add Field' }))
    fireEvent.click(screen.getByRole('radio', { name: /Short Text/ }))

    const nameInput = screen.getByLabelText('Field Name')
    fireEvent.change(nameInput, { target: { value: 'Client Name' } })

    // Auto-derived key + snippet preview.
    expect((screen.getByLabelText('Field Key') as HTMLInputElement).value).toBe('clientName')
    expect(screen.getByText(/clientName: \{ type: 'text', label: 'Client Name' \},/)).toBeTruthy()

    // A name colliding with an existing field key blocks the snippet.
    fireEvent.change(nameInput, { target: { value: 'Featured Image' } })
    expect(screen.getByText(/already exists on this type/)).toBeTruthy()
    expect(screen.queryByText('Copy snippet')).toBeNull()
  })

  it('shows a not-found notice for unknown slugs', async () => {
    const onNavigate = vi.fn()
    render(<PostTypeEditor slug="ghost" onNavigate={onNavigate} />)

    await waitFor(() => expect(screen.getByText('No post type named "ghost"')).toBeTruthy())
    fireEvent.click(screen.getByRole('button', { name: 'Back to Post Types' }))
    expect(onNavigate).toHaveBeenCalledWith('/posts/types')
  })
})
