import { describe, it, expect } from 'vitest'
import {
  GetNotificationsQuerySchema,
  MarkAsReadParamsSchema,
  CreateNotificationSchema,
  NotificationCategorySchema
} from '../api-schemas'

describe('GetNotificationsQuerySchema', () => {
  it('accepts valid limit', () => {
    const result = GetNotificationsQuerySchema.safeParse({ limit: '50' })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.limit).toBe(50) // Coerced to number
    }
  })

  it('applies default limit', () => {
    const result = GetNotificationsQuerySchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.limit).toBe(50)
    }
  })

  it('rejects limit > 100 (DoS prevention)', () => {
    const result = GetNotificationsQuerySchema.safeParse({ limit: '101' })
    expect(result.success).toBe(false)
  })

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

  it('rejects non-numeric limit', () => {
    const result = GetNotificationsQuerySchema.safeParse({ limit: 'abc' })
    expect(result.success).toBe(false)
  })

  it('accepts numeric limit', () => {
    const result = GetNotificationsQuerySchema.safeParse({ limit: 25 })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.limit).toBe(25)
    }
  })
})

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

  it('rejects non-UUID string', () => {
    const result = MarkAsReadParamsSchema.safeParse({ id: 'not-a-uuid' })
    expect(result.success).toBe(false)
  })

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

  it('rejects SQL injection attempt', () => {
    const result = MarkAsReadParamsSchema.safeParse({ id: "'; DROP TABLE notifications;--" })
    expect(result.success).toBe(false)
  })
})

describe('CreateNotificationSchema', () => {
  const validNotification = {
    userId: '123e4567-e89b-12d3-a456-426614174000',
    organizationId: '123e4567-e89b-12d3-a456-426614174001',
    category: 'info' as const,
    title: 'Test Notification',
    message: 'This is a test message'
  }

  it('accepts valid notification', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      actionUrl: 'https://example.com/action'
    })
    expect(result.success).toBe(true)
  })

  it('accepts notification without actionUrl', () => {
    const result = CreateNotificationSchema.safeParse(validNotification)
    expect(result.success).toBe(true)
  })

  it('rejects invalid category', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      category: 'invalid'
    })
    expect(result.success).toBe(false)
  })

  it('rejects title too long (DoS prevention)', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      title: 'a'.repeat(201)
    })
    expect(result.success).toBe(false)
  })

  it('rejects message too long (DoS prevention)', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      message: 'a'.repeat(1001)
    })
    expect(result.success).toBe(false)
  })

  it('accepts title at max length', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      title: 'a'.repeat(200)
    })
    expect(result.success).toBe(true)
  })

  it('accepts message at max length', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      message: 'a'.repeat(1000)
    })
    expect(result.success).toBe(true)
  })

  it('rejects invalid actionUrl', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      actionUrl: 'not-a-url'
    })
    expect(result.success).toBe(false)
  })

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

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

  it('trims whitespace from title and message', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      title: '  Test  ',
      message: '  Message  '
    })
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.title).toBe('Test')
      expect(result.data.message).toBe('Message')
    }
  })

  it('rejects empty title after trim', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      title: '   '
    })
    expect(result.success).toBe(false)
  })

  it('rejects empty message after trim', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      message: '   '
    })
    expect(result.success).toBe(false)
  })

  it('prevents unknown fields (strict mode - mass assignment prevention)', () => {
    const result = CreateNotificationSchema.safeParse({
      ...validNotification,
      unknownField: 'should fail'
    })
    expect(result.success).toBe(false)
  })
})

describe('NotificationCategorySchema', () => {
  it('accepts all valid categories', () => {
    const categories = ['info', 'queue', 'alert', 'error', 'system']
    categories.forEach((category) => {
      const result = NotificationCategorySchema.safeParse(category)
      expect(result.success).toBe(true)
    })
  })

  it('rejects invalid category', () => {
    const result = NotificationCategorySchema.safeParse('invalid')
    expect(result.success).toBe(false)
  })

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