import { describe, expect, it, vi } from 'vitest'
import { Hono } from 'hono'
import { TenantTier } from '@zync/types'
import type { AppEnv } from '../src/types'
import { authMiddleware } from '../src/middleware/auth'

describe('authenticated request durable-object offload', () => {
  it('uses the DO result as the authenticated request context', async () => {
    const fetch = vi.fn(async (_input: RequestInfo | URL, init?: RequestInit) => {
      const request = new Request(_input, init)
      expect(new URL(request.url).pathname).toBe('/authenticate')
      await expect(request.json()).resolves.toEqual({ token: 'signed-session' })
      return Response.json({
        ok: true,
        accessTokenHash: 'access-hash',
        sessionId: 'session-1',
        session: {
          sub: 'user-1',
          tid: 'tenant-1',
          role: 'OWNER',
          permissions: ['dashboard:read'],
          tier: TenantTier.FREELANCER,
          type: 'user',
          v: 0,
          iat: 1,
          exp: 2,
        },
      })
    })
    const env = {
      DB: { connectionString: 'postgresql://test:test@localhost/test' },
      AUTHWRITE_DO_SECRET: 'internal-secret',
      AUTHWRITE_DO: {
        idFromName: vi.fn(() => ({ toString: () => 'id' })),
        get: vi.fn(() => ({ fetch })),
      },
    } as unknown as AppEnv['Bindings']
    const app = new Hono<AppEnv>()
    app.use('/private', authMiddleware)
    app.get('/private', (c) => c.json({
      subject: c.get('session')?.sub,
      sessionId: c.get('sessionId'),
      accessTokenHash: c.get('accessTokenHash'),
    }))

    const response = await app.request('/private', {
      headers: { Cookie: 'zync_session=signed-session' },
    }, env)

    expect(response.status).toBe(200)
    expect(fetch).toHaveBeenCalledOnce()
    await expect(response.json()).resolves.toEqual({
      subject: 'user-1',
      sessionId: 'session-1',
      accessTokenHash: 'access-hash',
    })
  })
})
