/**
 * Sessions API Schemas - Unit Tests
 *
 * Tests Zod validation schemas for session management endpoints.
 * Validates security constraints: UUID format, length limits, strict mode.
 */

import { describe, it, expect } from 'vitest'
import {
  CreateSessionSchema,
  ExecuteTurnSchema,
  ListSessionsQuerySchema,
  SessionIdParamSchema,
  ExecutionIdParamsSchema,
  WebSocketSessionTurnSchema,
  UuidSchema
} from '../api-schemas'

describe('Sessions API Schemas', () => {
  describe('UuidSchema', () => {
    it('accepts valid UUID', () => {
      const result = UuidSchema.safeParse('123e4567-e89b-12d3-a456-426614174000')
      expect(result.success).toBe(true)
    })

    it('rejects invalid UUID format', () => {
      const result = UuidSchema.safeParse('not-a-uuid')
      expect(result.success).toBe(false)
      if (!result.success) {
        expect(result.error.message).toContain('Invalid UUID')
      }
    })

    it('rejects empty string', () => {
      const result = UuidSchema.safeParse('')
      expect(result.success).toBe(false)
    })
  })

  describe('SessionIdParamSchema', () => {
    it('accepts valid sessionId', () => {
      const result = SessionIdParamSchema.safeParse({
        sessionId: '123e4567-e89b-12d3-a456-426614174000'
      })
      expect(result.success).toBe(true)
    })

    it('rejects invalid sessionId UUID', () => {
      const result = SessionIdParamSchema.safeParse({
        sessionId: 'not-a-uuid'
      })
      expect(result.success).toBe(false)
    })

    it('prevents unknown fields (strict mode)', () => {
      const result = SessionIdParamSchema.safeParse({
        sessionId: '123e4567-e89b-12d3-a456-426614174000',
        organizationId: '123e4567-e89b-12d3-a456-426614174001'
      })
      expect(result.success).toBe(false)
      if (!result.success) {
        expect(result.error.message).toContain('organizationId')
      }
    })
  })

  describe('ExecutionIdParamsSchema', () => {
    it('accepts valid sessionId and executionId', () => {
      const result = ExecutionIdParamsSchema.safeParse({
        sessionId: '123e4567-e89b-12d3-a456-426614174000',
        executionId: '123e4567-e89b-12d3-a456-426614174001'
      })
      expect(result.success).toBe(true)
    })

    it('rejects invalid sessionId', () => {
      const result = ExecutionIdParamsSchema.safeParse({
        sessionId: 'invalid',
        executionId: '123e4567-e89b-12d3-a456-426614174001'
      })
      expect(result.success).toBe(false)
    })

    it('rejects invalid executionId', () => {
      const result = ExecutionIdParamsSchema.safeParse({
        sessionId: '123e4567-e89b-12d3-a456-426614174000',
        executionId: 'invalid'
      })
      expect(result.success).toBe(false)
    })
  })

  describe('CreateSessionSchema', () => {
    it('accepts valid session data with agent ID', () => {
      const result = CreateSessionSchema.safeParse({
        resourceId: 'basic-agent',
        metadata: { key: 'value' }
      })
      expect(result.success).toBe(true)
    })

    it('accepts valid session data with workflow ID', () => {
      const result = CreateSessionSchema.safeParse({
        resourceId: 'linear-test-workflow',
        metadata: { key: 'value' }
      })
      expect(result.success).toBe(true)
    })

    it('accepts optional userId', () => {
      const result = CreateSessionSchema.safeParse({
        resourceId: 'basic-agent',
        userId: '123e4567-e89b-12d3-a456-426614174001'
      })
      expect(result.success).toBe(true)
    })

    it('rejects empty resourceId', () => {
      const result = CreateSessionSchema.safeParse({
        resourceId: ''
      })
      expect(result.success).toBe(false)
    })

    it('rejects resourceId over 100 characters', () => {
      const result = CreateSessionSchema.safeParse({
        resourceId: 'x'.repeat(101)
      })
      expect(result.success).toBe(false)
    })

    it('rejects invalid userId UUID', () => {
      const result = CreateSessionSchema.safeParse({
        resourceId: 'basic-agent',
        userId: 'not-a-uuid'
      })
      expect(result.success).toBe(false)
    })

    it('prevents organizationId injection (strict mode)', () => {
      const result = CreateSessionSchema.safeParse({
        resourceId: 'basic-agent',
        organizationId: '123e4567-e89b-12d3-a456-426614174001'
      })
      expect(result.success).toBe(false)
      if (!result.success) {
        expect(result.error.message).toContain('organizationId')
      }
    })

    it('prevents unknown fields', () => {
      const result = CreateSessionSchema.safeParse({
        resourceId: 'basic-agent',
        hackField: 'malicious'
      })
      expect(result.success).toBe(false)
    })
  })

  describe('ExecuteTurnSchema', () => {
    it('accepts string input', () => {
      const result = ExecuteTurnSchema.safeParse({
        input: 'Hello, agent!'
      })
      expect(result.success).toBe(true)
    })

    it('accepts object input with message', () => {
      const result = ExecuteTurnSchema.safeParse({
        input: { message: 'Hello, agent!' }
      })
      expect(result.success).toBe(true)
    })

    it('accepts JSON-serializable input', () => {
      const result = ExecuteTurnSchema.safeParse({
        input: { task: 'analyze', data: [1, 2, 3] }
      })
      expect(result.success).toBe(true)
    })

    it('accepts optional metadata', () => {
      const result = ExecuteTurnSchema.safeParse({
        input: 'Hello',
        metadata: { source: 'test' }
      })
      expect(result.success).toBe(true)
    })

    it('rejects empty string input', () => {
      const result = ExecuteTurnSchema.safeParse({
        input: ''
      })
      expect(result.success).toBe(false)
      if (!result.success) {
        expect(result.error.message).toContain('100,000 characters')
      }
    })

    it('rejects input over 100k characters', () => {
      const result = ExecuteTurnSchema.safeParse({
        input: 'x'.repeat(100001)
      })
      expect(result.success).toBe(false)
      if (!result.success) {
        expect(result.error.message).toContain('100,000 characters')
      }
    })

    it('accepts input at exactly 100k characters', () => {
      const result = ExecuteTurnSchema.safeParse({
        input: 'x'.repeat(100000)
      })
      expect(result.success).toBe(true)
    })

    it('rejects object input over 100k characters when serialized', () => {
      const result = ExecuteTurnSchema.safeParse({
        input: { message: 'x'.repeat(100001) }
      })
      expect(result.success).toBe(false)
    })

    it('prevents unknown fields (strict mode)', () => {
      const result = ExecuteTurnSchema.safeParse({
        input: 'Hello',
        userId: 'user-123'
      })
      expect(result.success).toBe(false)
    })
  })

  describe('ListSessionsQuerySchema', () => {
    it('accepts empty query (uses defaults)', () => {
      const result = ListSessionsQuerySchema.safeParse({})
      expect(result.success).toBe(true)
      if (result.success) {
        expect(result.data.limit).toBe(20) // Default value
      }
    })

    it('coerces limit to number', () => {
      const result = ListSessionsQuerySchema.safeParse({
        limit: '50' // String from query param
      })
      expect(result.success).toBe(true)
      if (result.success) {
        expect(result.data.limit).toBe(50)
        expect(typeof result.data.limit).toBe('number')
      }
    })

    it('accepts valid userId filter', () => {
      const result = ListSessionsQuerySchema.safeParse({
        userId: '123e4567-e89b-12d3-a456-426614174000'
      })
      expect(result.success).toBe(true)
    })

    it('accepts valid resourceId filter', () => {
      const result = ListSessionsQuerySchema.safeParse({
        resourceId: '123e4567-e89b-12d3-a456-426614174000'
      })
      expect(result.success).toBe(true)
    })

    it('rejects invalid userId UUID', () => {
      const result = ListSessionsQuerySchema.safeParse({
        userId: 'not-a-uuid'
      })
      expect(result.success).toBe(false)
    })

    it('rejects limit below 1', () => {
      const result = ListSessionsQuerySchema.safeParse({
        limit: 0
      })
      expect(result.success).toBe(false)
    })

    it('rejects limit over 100', () => {
      const result = ListSessionsQuerySchema.safeParse({
        limit: 200
      })
      expect(result.success).toBe(false)
    })

    it('accepts limit at 100', () => {
      const result = ListSessionsQuerySchema.safeParse({
        limit: 100
      })
      expect(result.success).toBe(true)
    })

    it('accepts limit at 1', () => {
      const result = ListSessionsQuerySchema.safeParse({
        limit: 1
      })
      expect(result.success).toBe(true)
    })

    it('prevents unknown fields (strict mode)', () => {
      const result = ListSessionsQuerySchema.safeParse({
        limit: 20,
        organizationId: '123e4567-e89b-12d3-a456-426614174000'
      })
      expect(result.success).toBe(false)
    })
  })

  describe('WebSocketSessionTurnSchema', () => {
    it('accepts valid message', () => {
      const result = WebSocketSessionTurnSchema.safeParse({
        type: 'session:turn',
        input: 'Hello, agent!'
      })
      expect(result.success).toBe(true)
    })

    it('accepts object input', () => {
      const result = WebSocketSessionTurnSchema.safeParse({
        type: 'session:turn',
        input: { message: 'Hello' }
      })
      expect(result.success).toBe(true)
    })

    it('rejects wrong message type', () => {
      const result = WebSocketSessionTurnSchema.safeParse({
        type: 'wrong:type',
        input: 'Hello'
      })
      expect(result.success).toBe(false)
    })

    it('rejects empty input', () => {
      const result = WebSocketSessionTurnSchema.safeParse({
        type: 'session:turn',
        input: ''
      })
      expect(result.success).toBe(false)
    })

    it('rejects input over 100k characters', () => {
      const result = WebSocketSessionTurnSchema.safeParse({
        type: 'session:turn',
        input: 'x'.repeat(100001)
      })
      expect(result.success).toBe(false)
    })

    it('prevents unknown fields (strict mode)', () => {
      const result = WebSocketSessionTurnSchema.safeParse({
        type: 'session:turn',
        input: 'Hello',
        sessionId: 'session-123'
      })
      expect(result.success).toBe(false)
    })
  })
})
