import { beforeEach, describe, expect, it, vi } from 'vitest'
import { Hono } from 'hono'
import type { AppEnv } from '../src/types'

const mockGetCustomerWithStats = vi.fn()
const mockUpdateCustomer = vi.fn()
const mockArchiveCustomer = vi.fn()

vi.mock('../src/middleware/auth', () => ({
  authMiddleware: async (
    c: { set: (key: string, value: unknown) => void },
    next: () => Promise<void>,
  ) => {
    c.set('session', { type: 'user', sub: 'user-1', tid: 'tenant-1', permissions: ['customers:read'] })
    c.set('db', {})
    await next()
  },
}))

vi.mock('../src/middleware/guards', () => ({
  requirePermission: () => async (_c: unknown, next: () => Promise<void>) => next(),
}))

vi.mock('@zync/db/queries', () => ({
  getCustomerWithStats: (...args: unknown[]) => mockGetCustomerWithStats(...args),
  updateCustomer: (...args: unknown[]) => mockUpdateCustomer(...args),
  archiveCustomer: (...args: unknown[]) => mockArchiveCustomer(...args),
  OpenInvoicesError: class OpenInvoicesError extends Error {},
}))

describe('customer detail id validation', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockGetCustomerWithStats.mockResolvedValue(null)
  })

  it.each([
    ['GET', undefined],
    ['PATCH', JSON.stringify({ name: 'Renamed' })],
    ['DELETE', undefined],
  ])('rejects the UI-only new path before the %s UUID query', async (method, body) => {
    const { customersIndexRoute } = await import('../src/routes/customers/index')
    const app = new Hono<AppEnv>()
    app.use('*', async (c, next) => {
      c.set('session', { type: 'user', sub: 'user-1', tid: 'tenant-1', permissions: ['customers:read'] })
      c.set('db', {})
      await next()
    })
    app.route('/api/customers', customersIndexRoute)

    const response = await app.request('/api/customers/new', {
      method,
      headers: body ? { 'Content-Type': 'application/json' } : undefined,
      body,
    })

    expect(response.status).toBe(400)
    await expect(response.json()).resolves.toEqual({ error: 'Invalid customer id' })
    expect(mockGetCustomerWithStats).not.toHaveBeenCalled()
    expect(mockUpdateCustomer).not.toHaveBeenCalled()
    expect(mockArchiveCustomer).not.toHaveBeenCalled()
  })
})
