import { describe, expect, it, vi } from 'vitest'
import { composeServerAuth, type AuthEngine } from '../src/server.js'

const principal = { userId: 'user-1', sessionId: 'session-1', roles: ['admin'] }

function fakeEngine(): AuthEngine {
  return {
    signIn: vi.fn(async () => ({ principal, accessToken: 'access', refreshToken: 'refresh' })),
    signOut: vi.fn(async () => undefined),
    verifySession: vi.fn(async (token) => token === 'access' ? principal : null),
    refresh: vi.fn(async () => ({ principal, accessToken: 'next-access' })),
    createUser: vi.fn(async () => ({ userId: 'user-1' })),
    setPassword: vi.fn(async () => undefined),
    verifyPassword: vi.fn(async () => true),
  }
}

describe('published auth composition', () => {
  it('uses the configured access cookie and server-side role guard', async () => {
    const engine = fakeEngine()
    const auth = composeServerAuth(engine)
    const resolved = await auth.getPrincipal({ cookie: '__Host-pdf2html_access=access' })

    expect(resolved).toEqual(principal)
    expect(auth.requireAdmin(resolved)).toEqual(principal)
    expect(engine.verifySession).toHaveBeenCalledWith('access')
  })

  it('returns null when the cookie is missing or the injected engine rejects its token', async () => {
    const engine = fakeEngine()
    const auth = composeServerAuth(engine)

    await expect(auth.getPrincipal({})).resolves.toBeNull()
    await expect(auth.getPrincipal({ cookie: '__Host-pdf2html_access=invalid' })).resolves.toBeNull()
  })

  it('rejects a missing or under-privileged principal at the public role guard', () => {
    const auth = composeServerAuth(fakeEngine())
    expect(() => auth.requireAdmin(null)).toThrow()
    expect(() => auth.requireAdmin({ ...principal, roles: ['user'] })).toThrow()
  })

  it('delegates sign-in, refresh, and sign-out to the injected engine without network calls', async () => {
    const engine = fakeEngine()
    const auth = composeServerAuth(engine)
    const credentials = { email: 'person@example.invalid', password: ['fixture', 'password'].join('-') }

    await auth.signIn(credentials)
    await auth.refresh('refresh-token')
    await auth.signOut('session-1', 'refresh-token')

    expect(engine.signIn).toHaveBeenCalledWith(credentials)
    expect(engine.refresh).toHaveBeenCalledWith('refresh-token')
    expect(engine.signOut).toHaveBeenCalledWith('session-1', 'refresh-token')
  })

  it('loads every documented public package root and subpath', async () => {
    const modules = await Promise.all([
      import('@platform-modules/auth'),
      import('@platform-modules/auth/engine-custom'),
      import('@platform-modules/auth/engine-better-auth'),
      import('@platform-modules/auth/otp-email'),
      import('@platform-modules/auth/api-keys'),
      import('@platform-modules/auth/oauth-provider'),
      import('@platform-modules/auth-react'),
    ])

    expect(modules.every((entry) => Object.keys(entry).length > 0)).toBe(true)
  })
})
