import { beforeEach, describe, expect, it, vi } from 'vitest'
import { Hono } from 'hono'

vi.mock('@zync/db/queries', () => ({
  createDb: vi.fn(() => ({})),
  listTaxRates: vi.fn().mockResolvedValue([]),
  listVatRatesForAdmin: vi.fn().mockResolvedValue([]),
  addTaxRate: vi.fn(),
  TaxRateConflictError: class TaxRateConflictError extends Error {},
  TaxRateValidationError: class TaxRateValidationError extends Error {},
}))

vi.mock('../src/middleware/admin-auth', () => ({
  adminAuthMiddleware: async (c: { set: (key: string, value: unknown) => void }, next: () => Promise<void>) => {
    c.set('session', {
      sub: 'admin-1',
      type: 'admin',
      totp_verified: true,
      role: 'BILLING',
      permissions: ['admin.billing:read', 'admin.billing:write'],
    })
    await next()
  },
}))

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

import { adminTaxRatesRoutes } from '../src/routes/admin/tax-rates'
import type { AppEnv } from '../src/types'

function appWithRoute() {
  const app = new Hono<AppEnv>()
  app.route('/api/admin/tax-rates', adminTaxRatesRoutes)
  return app
}

describe('admin tax rates permissions', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('rejects non-SUPER_ADMIN reads even when billing permissions are present', async () => {
    const res = await appWithRoute().request('/api/admin/tax-rates?country=IL')

    expect(res.status).toBe(403)
    await expect(res.json()).resolves.toMatchObject({ error: 'Forbidden' })
  })

  it('rejects non-SUPER_ADMIN writes even when billing permissions are present', async () => {
    const res = await appWithRoute().request('/api/admin/tax-rates', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Origin: 'https://admin.zync.is',
      },
      body: JSON.stringify({
        countryCode: 'IL',
        taxType: 'corporate_income',
        rate: '0.2300',
        effectiveFrom: '2026-08-01',
      }),
    })

    expect(res.status).toBe(403)
    await expect(res.json()).resolves.toMatchObject({ error: 'Forbidden' })
  })
})
