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

const requirePermissionMock = vi.fn(() => async (_c: unknown, next: () => Promise<void>) => next())
const listVendorsMock = vi.fn(async () => ({ items: [], total: 0 }))
const getVendorMock = vi.fn(async () => ({
  id: 'vendor-1',
  tenantId: 'tenant-1',
  name: 'AWS',
  taxId: '514000000',
  withholdingRate: null,
  withholdingCertNumber: null,
  withholdingCertExpiry: null,
  withholdingCertR2Key: null,
  defaultCategory: null,
  defaultVatDeductible: true,
  paymentTermsDays: 30,
  email: null,
  phone: null,
  address: null,
  notes: null,
  isArchived: false,
  createdAt: new Date('2026-01-01T00:00:00.000Z'),
  updatedAt: new Date('2026-01-02T00:00:00.000Z'),
  ytdSpend: '10680.00',
  expenseCount: 2,
  linkedExpensesTotal: '10680.00',
  expenses: [
    {
      id: 'expense-1',
      expenseDate: '2026-06-01',
      amount: '5000.00',
      currency: 'ILS',
      category: 'hosting',
      status: 'COMPLETED',
      vendorName: 'AWS',
    },
  ],
}))
const createVendorMock = vi.fn()
const updateVendorMock = vi.fn()
const archiveVendorMock = vi.fn()
const suggestVendorsMock = vi.fn(async () => [])

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

vi.mock('../src/middleware/guards', () => ({
  requirePermission: (...args: unknown[]) => requirePermissionMock(...args),
}))

vi.mock('@zync/db/queries', () => ({
  listVendors: (...args: unknown[]) => listVendorsMock(...args),
  getVendor: (...args: unknown[]) => getVendorMock(...args),
  createVendor: (...args: unknown[]) => createVendorMock(...args),
  updateVendor: (...args: unknown[]) => updateVendorMock(...args),
  archiveVendor: (...args: unknown[]) => archiveVendorMock(...args),
  suggestVendors: (...args: unknown[]) => suggestVendorsMock(...args),
}))

describe('vendor routes', () => {
  it('guards vendor CRUD with expenses permissions', async () => {
    await import('../src/routes/vendors')

    expect(requirePermissionMock).toHaveBeenCalledWith('expenses:read')
    expect(requirePermissionMock).toHaveBeenCalledWith('expenses:write')
    expect(requirePermissionMock).not.toHaveBeenCalledWith('vendors:read')
    expect(requirePermissionMock).not.toHaveBeenCalledWith('vendors:write')
  })

  it('returns vendor detail with linked expense summary', async () => {
    const { vendorRoutes } = await import('../src/routes/vendors')
    const app = new Hono<AppEnv>()
    app.route('/api/vendors', vendorRoutes)

    const res = await app.request('/api/vendors/vendor-1')
    expect(res.status).toBe(200)

    const body = await res.json()
    expect(body.expenseCount).toBe(2)
    expect(body.linkedExpensesTotal).toBe('10680.00')
    expect(body.expenses).toHaveLength(1)
  })
})
