import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useTagDirectoryStore } from '../src/stores/tagDirectory.js'

function stubFetch(handler) {
  globalThis.fetch = vi.fn(async (url, init) => {
    const { status, body } = handler(url, init)
    return {
      ok: status >= 200 && status < 300,
      status,
      statusText: String(status),
      text: async () => (body == null ? '' : JSON.stringify(body))
    }
  })
}

describe('tagDirectory store: rename / merge', () => {
  beforeEach(() => setActivePinia(createPinia()))
  afterEach(() => { vi.restoreAllMocks() })

  it('rename success patches the card name in place', async () => {
    const store = useTagDirectoryStore()
    store.cards.push({ id: 1, name: 'old', kind: 'general' })
    stubFetch(() => ({ status: 200, body: { id: 1, name: 'new', kind: 'general' } }))
    const res = await store.rename(1, 'new')
    expect(res.collision).toBeUndefined()
    expect(store.cards[0].name).toBe('new')
  })

  it('rename 409 resolves a collision object (does not throw)', async () => {
    const store = useTagDirectoryStore()
    store.cards.push({ id: 7, name: 'dupe', kind: 'general' })
    stubFetch(() => ({
      status: 409,
      body: {
        error: 'exists',
        target: { id: 2, name: 'Canon' },
        source_image_count: 5,
        will_alias: true
      }
    }))
    const res = await store.rename(7, 'Canon')
    expect(res.collision).toEqual({
      sourceId: 7,
      sourceName: 'dupe',
      target: { id: 2, name: 'Canon' },
      sourceImageCount: 5,
      willAlias: true
    })
    expect(store.cards[0].name).toBe('dupe') // unchanged
  })

  it('merge removes the source card optimistically', async () => {
    const store = useTagDirectoryStore()
    store.cards.push({ id: 7, name: 'dupe' }, { id: 2, name: 'Canon' })
    stubFetch(() => ({
      status: 200,
      body: {
        target: { id: 2, name: 'Canon', kind: 'general' },
        merged_count: 3,
        alias_created: true,
        source_deleted: true
      }
    }))
    const res = await store.merge(7, 2)
    expect(store.cards.map(c => c.id)).toEqual([2])
    expect(res.merged_count).toBe(3)
  })

  it('rename non-409 error rethrows', async () => {
    const store = useTagDirectoryStore()
    store.cards.push({ id: 1, name: 'x' })
    stubFetch(() => ({ status: 400, body: { error: 'bad' } }))
    await expect(store.rename(1, '')).rejects.toThrow()
  })
})
