import { eq } from 'drizzle-orm'
import { beforeEach, describe, expect, it } from 'vitest'
import type { Querier } from '@platform-modules/db'
import { createPgliteClient } from '../../db/src/postgres/pglite.js'
import { ContentAuthzError, type Actor } from './authz.js'
import { contentEntries, contentEntryTerms, contentSchema, contentTerms, type ContentSchema } from './schema.js'
import { setupTaxonomyDb } from './taxonomy.test-helpers.js'
import {
  TermHasChildrenError,
  TermNotFoundError,
  createTerm,
  deleteTerm,
} from './taxonomy.js'

const manager: Actor = { id: 'mgr-1', canManageTaxonomy: true }
const stranger: Actor = { id: 'stranger' }

describe('deleteTerm', () => {
  let d: Querier<ContentSchema>
  beforeEach(async () => {
    d = await setupTaxonomyDb(createPgliteClient({ schema: contentSchema }))
  })

  it('deletes a leaf term and cascades its join rows', async () => {
    const term = await createTerm(d, { taxonomy: 'tag', slug: 'leaf', name: 'Leaf' }, manager)
    const [entry] = await d
      .insert(contentEntries)
      .values({ slug: 'e1', type: 'post', title: 'E', author: 'u1', lastEditedBy: 'u1' })
      .returning()
    await d.insert(contentEntryTerms).values({ entryId: entry!.id, termId: term.id })

    await deleteTerm(d, term.id, manager)

    const terms = await d.select().from(contentTerms).where(eq(contentTerms.id, term.id))
    expect(terms).toHaveLength(0)
    const joins = await d.select().from(contentEntryTerms).where(eq(contentEntryTerms.termId, term.id))
    expect(joins).toHaveLength(0)
  })

  it('rejects delete when term has children', async () => {
    const parent = await createTerm(d, { taxonomy: 'category', slug: 'p', name: 'P' }, manager)
    await createTerm(d, { taxonomy: 'category', slug: 'c', name: 'C', parentId: parent.id }, manager)

    await expect(deleteTerm(d, parent.id, manager)).rejects.toBeInstanceOf(TermHasChildrenError)
    const still = await d.select().from(contentTerms).where(eq(contentTerms.id, parent.id))
    expect(still).toHaveLength(1)
  })

  it('throws TermNotFoundError for unknown id', async () => {
    await expect(
      deleteTerm(d, '00000000-0000-4000-8000-000000000001', manager),
    ).rejects.toBeInstanceOf(TermNotFoundError)
  })

  it('denies non-manage actor', async () => {
    const term = await createTerm(d, { taxonomy: 'tag', slug: 'x', name: 'X' }, manager)
    await expect(deleteTerm(d, term.id, stranger)).rejects.toBeInstanceOf(ContentAuthzError)
  })
})
