import { describe, expect, it } from 'vitest'
import { buildNavItems } from '../../layout/Sidebar.js'

/**
 * Regression coverage for the Posts area sidebar grouping.
 *
 * The reference design shows a single "Posts" parent with two fixed
 * children — All Posts and Post Types — even when the config defines
 * multiple post-type collections (Blog, Case Studies, News, ...). That
 * collapsing is fragile (it's tempting to enumerate each collection
 * as its own sidebar entry) so we lock the contract with explicit
 * tests.
 */

describe('buildNavItems', () => {
  it('returns the default tree when no collections are provided', () => {
    const items = buildNavItems({})
    const posts = items.find((i) => i.path === '/posts')
    expect(posts).toBeDefined()
    expect(posts?.children?.map((c) => c.path)).toEqual(['/posts', '/posts/types'])
    // Pages no longer carries children — Saved Sections / Templates moved
    // under the dedicated Templates parent.
    const pages = items.find((i) => i.path === '/pages')
    expect(pages?.children ?? []).toEqual([])
    // Templates is its own item with Saved Sections + Widgets.
    const templates = items.find((i) => i.path === '/page-templates')
    expect(templates?.children?.map((c) => c.path)).toEqual(['/saved-sections', '/widgets'])
  })

  it('exposes Templates as a top-level Content item with Saved Sections + Widgets', () => {
    const items = buildNavItems({
      collections: {
        pages: { slug: 'pages', labels: { singular: 'Page', plural: 'Pages' }, type: 'page' },
      },
    })
    const templates = items.find((i) => i.path === '/page-templates')
    expect(templates).toBeDefined()
    expect(templates?.group).toBe('Content')
    expect(templates?.children?.map((c) => c.label)).toEqual(['Saved Sections', 'Widgets'])
    // Templates is NOT nested under Pages.
    const pages = items.find((i) => i.path === '/pages')
    expect(pages?.children ?? []).toEqual([])
  })

  it('collapses every type:post collection under a single Posts parent', () => {
    const items = buildNavItems({
      collections: {
        blog: { slug: 'blog', labels: { singular: 'Blog Post', plural: 'Blog' }, type: 'post' },
        'case-studies': {
          slug: 'case-studies',
          labels: { singular: 'Case Study', plural: 'Case Studies' },
          type: 'post',
        },
        news: { slug: 'news', labels: { singular: 'News Item', plural: 'News' }, type: 'post' },
        pages: { slug: 'pages', labels: { singular: 'Page', plural: 'Pages' }, type: 'page' },
      },
    })

    // Exactly one /posts entry, regardless of how many post types exist.
    const postEntries = items.filter((i) => i.path === '/posts')
    expect(postEntries).toHaveLength(1)

    // Children are still the fixed pair — the per-type collections
    // are NOT enumerated as sidebar siblings.
    const children = postEntries[0]?.children?.map((c) => c.path)
    expect(children).toEqual(['/posts', '/posts/types'])

    // No per-type slug ended up as a top-level sidebar item.
    const slugPaths = items.map((i) => i.path)
    for (const slug of ['blog', 'case-studies', 'news']) {
      expect(slugPaths).not.toContain(`/${slug}`)
    }
  })

  it('treats admin.group=Posts (case-insensitive) as a synonym for type=post', () => {
    const items = buildNavItems({
      collections: {
        reviews: {
          slug: 'reviews',
          labels: { singular: 'Review', plural: 'Reviews' },
          // Intentionally NOT type:'post' — relying on the group marker.
          admin: { group: 'posts' },
        },
      },
    })
    expect(items.some((i) => i.path === '/posts')).toBe(true)
    expect(items.some((i) => i.path === '/reviews')).toBe(false)
  })

  it('omits the Posts parent entirely when no post-type collections exist', () => {
    const items = buildNavItems({
      collections: {
        pages: { slug: 'pages', labels: { singular: 'Page', plural: 'Pages' }, type: 'page' },
      },
    })
    expect(items.some((i) => i.path === '/posts')).toBe(false)
  })

  it('places Pages above Posts, both under the CONTENT group', () => {
    const items = buildNavItems({
      collections: {
        blog: { slug: 'blog', labels: { singular: 'Blog Post', plural: 'Blog' }, type: 'post' },
        pages: { slug: 'pages', labels: { singular: 'Page', plural: 'Pages' }, type: 'page' },
      },
    })

    const pagesIdx = items.findIndex((i) => i.path === '/pages')
    const postsIdx = items.findIndex((i) => i.path === '/posts')
    const mediaIdx = items.findIndex((i) => i.path === '/media')

    // Pages comes before Posts, and both come before the static
    // content destinations.
    expect(pagesIdx).toBeGreaterThanOrEqual(0)
    expect(pagesIdx).toBeLessThan(postsIdx)
    expect(postsIdx).toBeLessThan(mediaIdx)

    // Both are tagged Content so the single CONTENT header sits above
    // Pages (the first Content item in the tree).
    expect(items[pagesIdx]?.group).toBe('Content')
    expect(items[postsIdx]?.group).toBe('Content')

    // The first item carrying group 'Content' is Pages — i.e. the
    // CONTENT header renders directly above it.
    const firstContent = items.find((i) => i.group === 'Content')
    expect(firstContent?.path).toBe('/pages')
  })

  it('defaults: Pages is the first CONTENT item, above Posts', () => {
    const items = buildNavItems({})
    const pagesIdx = items.findIndex((i) => i.path === '/pages')
    const postsIdx = items.findIndex((i) => i.path === '/posts')
    expect(items[pagesIdx]?.group).toBe('Content')
    expect(items[postsIdx]?.group).toBe('Content')
    expect(pagesIdx).toBeLessThan(postsIdx)
    expect(items.find((i) => i.group === 'Content')?.path).toBe('/pages')
  })

  it('renders an admin.group=Content collection (Menus) as its own Content item', () => {
    const items = buildNavItems({
      collections: {
        pages: { slug: 'pages', labels: { singular: 'Page', plural: 'Pages' }, type: 'page' },
        navigations: {
          slug: 'navigations',
          labels: { singular: 'Menu', plural: 'Menus' },
          admin: { group: 'Content', icon: 'navigation' },
        },
      },
    })

    const menus = items.find((i) => i.path === '/navigations')
    expect(menus).toBeDefined()
    expect(menus?.label).toBe('Menus')
    expect(menus?.group).toBe('Content')
    // It is a flat Content entry, not a child of Posts/Templates/Pages.
    expect(menus?.children).toBeUndefined()
    // Lands after the static Content destinations, before Settings.
    const menusIdx = items.findIndex((i) => i.path === '/navigations')
    const scriptIdx = items.findIndex((i) => i.path === '/script-tags')
    const settingsIdx = items.findIndex((i) => i.path === '/settings')
    expect(menusIdx).toBeGreaterThan(scriptIdx)
    expect(menusIdx).toBeLessThan(settingsIdx)
  })

  it('keeps standard Content/Settings entries after collections', () => {
    const items = buildNavItems({
      collections: {
        blog: { slug: 'blog', labels: { singular: 'Blog Post', plural: 'Blog' }, type: 'post' },
      },
    })
    const paths = items.map((i) => i.path)
    expect(paths).toContain('/media')
    expect(paths).toContain('/forms')
    expect(paths).toContain('/seo')
    expect(paths).toContain('/script-tags')
    expect(paths).toContain('/settings')
    // Users + API Keys moved into Settings tabs — they are no longer
    // standalone sidebar destinations.
    expect(paths).not.toContain('/users')
    expect(paths).not.toContain('/api-keys')
  })
})
