import { describe, expect, it } from 'vitest'
import { maintenanceGuard } from './maintenance.js'

describe('maintenanceGuard', () => {
  it('disabled => never blocked, regardless of roles', () => {
    expect(maintenanceGuard({ enabled: false }, null).blocked).toBe(false)
    expect(maintenanceGuard({ enabled: false }, ['user']).blocked).toBe(false)
  })

  it('enabled + anonymous principal => 503 with Retry-After (default 3600)', () => {
    const v = maintenanceGuard({ enabled: true, message: 'back soon' }, null)
    expect(v.blocked).toBe(true)
    expect(v.status).toBe(503)
    expect(v.headers?.['Retry-After']).toBe('3600')
    expect(v.message).toBe('back soon')
  })

  it('a custom retryAfterSec is reflected in Retry-After', () => {
    const v = maintenanceGuard({ enabled: true, retryAfterSec: 120 }, ['user'])
    expect(v.headers?.['Retry-After']).toBe('120')
  })

  it('HARD FLOOR: admin/owner are ALWAYS admitted even when allowRoles omits them', () => {
    expect(maintenanceGuard({ enabled: true, allowRoles: ['editor'] }, ['admin']).blocked).toBe(false)
    expect(maintenanceGuard({ enabled: true, allowRoles: ['editor'] }, ['owner']).blocked).toBe(false)
  })

  it('HARD FLOOR: allowRoles:[] still admits the operator (never locks everyone out)', () => {
    expect(maintenanceGuard({ enabled: true, allowRoles: [] }, ['owner']).blocked).toBe(false)
  })

  it('allowRoles ADDS extra admitted roles', () => {
    expect(maintenanceGuard({ enabled: true, allowRoles: ['editor'] }, ['editor']).blocked).toBe(false)
  })

  it('a non-operator, non-allowed role is blocked', () => {
    expect(maintenanceGuard({ enabled: true, allowRoles: ['editor'] }, ['user']).blocked).toBe(true)
  })

  it('HARD FLOOR: a malformed (non-array) principalRoles does not throw — operator floor survives garbage input', () => {
    // A JS host can violate the `string[]` type across the trust boundary; the guard must
    // still return a verdict (a throw would lock out admin/owner too). Non-array => empty.
    expect(() => maintenanceGuard({ enabled: true }, 'admin' as never)).not.toThrow()
    const v = maintenanceGuard({ enabled: true }, 'admin' as never)
    expect(v.blocked).toBe(true) // a string is NOT a roles array — fail-closed to no roles
  })

  it('HARD FLOOR: a malformed (non-array) allowRoles does not throw — operator still admitted', () => {
    expect(() => maintenanceGuard({ enabled: true, allowRoles: 'editor' as never }, ['admin'])).not.toThrow()
    // garbage allowRoles is ignored, but the operator floor still admits admin/owner
    expect(maintenanceGuard({ enabled: true, allowRoles: 'editor' as never }, ['owner']).blocked).toBe(false)
    // and the garbage no longer leaks its characters into the allow-set
    expect(maintenanceGuard({ enabled: true, allowRoles: 'editor' as never }, ['e']).blocked).toBe(true)
  })
})
