/**
 * Auth token lifecycle + rate-limit regression — S1-004 / S1-007 / S1-008.
 */
import { describe, it, expect, vi } from 'vitest'
import { Hono } from 'hono'
import {
  consumeSignedTokenJti,
  PASSWORD_RESET_JTI_PREFIX,
  signSignedToken,
  verifySignedToken,
} from '@zync/auth'
import { signupRoute } from '../src/routes/auth/signup'
import { passwordRoute } from '../src/routes/auth/password'
import type { AppEnv } from '../src/types'

const ORIGIN = 'https://app.zync.is'

describe('password reset token single-use (S1-004)', () => {
  it('signSignedToken includes a jti claim', async () => {
    const token = await signSignedToken(
      { sub: 'user-1', purpose: 'password_reset' },
      'test-secret',
      3600,
    )
    const claims = await verifySignedToken(token, 'test-secret')
    expect(typeof claims.jti).toBe('string')
    expect(claims.jti).toBeTruthy()
  })

  it('rejects reuse of the same reset token jti', async () => {
    const store = new Map<string, string>()
    const kv = {
      get: vi.fn(async (key: string) => store.get(key) ?? null),
      put: vi.fn(async (key: string, value: string) => {
        store.set(key, value)
      }),
    } as unknown as KVNamespace

    const first = await consumeSignedTokenJti(kv, PASSWORD_RESET_JTI_PREFIX, 'jti-abc', 3600)
    expect(first).toBe(true)

    const second = await consumeSignedTokenJti(kv, PASSWORD_RESET_JTI_PREFIX, 'jti-abc', 3600)
    expect(second).toBe(false)
  })
})

describe('auth rate limits (S1-007 / S1-008)', () => {
  it('signup returns 429 when RATE_LIMITER_AUTH denies', async () => {
    const app = new Hono<AppEnv>()
    app.route('/', signupRoute)

    const res = await app.request(
      '/signup',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'CF-Connecting-IP': '203.0.113.10',
        },
        body: JSON.stringify({
          email: 'new@example.com',
          password: 'password123',
          businessName: 'New User',
        }),
      },
      {
        RATE_LIMITER_AUTH: {
          limit: vi.fn(async () => ({ success: false })),
        },
      } as never,
    )

    expect(res.status).toBe(429)
    const body = (await res.json()) as { error: string }
    expect(body.error).toBe('Too many requests')
  })

  it('reset-password confirm returns 429 when RATE_LIMITER_AUTH denies', async () => {
    const app = new Hono<AppEnv>()
    app.route('/', passwordRoute)

    const res = await app.request(
      '/reset-password/confirm',
      {
        method: 'POST',
        headers: {
          Origin: ORIGIN,
          'Content-Type': 'application/json',
          'CF-Connecting-IP': '203.0.113.11',
        },
        body: JSON.stringify({ token: 'invalid', password: 'newpassword' }),
      },
      {
        RATE_LIMITER_AUTH: {
          limit: vi.fn(async () => ({ success: false })),
        },
      } as never,
    )

    expect(res.status).toBe(429)
    const body = (await res.json()) as { error: string }
    expect(body.error).toBe('Too many requests')
  })
})
