import { describe, it, expect, vi, beforeEach } from 'vitest'
import { GET, POST } from './route'
import { NextRequest } from 'next/server'

vi.mock('next-auth', () => ({ getServerSession: vi.fn() }))
vi.mock('@/lib/auth', () => ({ authOptions: {} }))
vi.mock('@/lib/prisma', () => ({
  prisma: {
    review: {
      findMany: vi.fn().mockResolvedValue([]),
      findFirst: vi.fn().mockResolvedValue(null),
      create: vi.fn().mockResolvedValue({ id: 'r1', rating: 5, status: 'PENDING' }),
    },
  },
}))
vi.mock('isomorphic-dompurify', () => ({ default: { sanitize: (s: string) => s } }))

import { getServerSession } from 'next-auth'
import { prisma } from '@/lib/prisma'

describe('GET /api/spots/[id]/reviews', () => {
  it('returns reviews list', async () => {
    const res = await GET(new NextRequest('http://localhost'), { params: { id: 'spot-1' } })
    expect(res.status).toBe(200)
    const data = await res.json()
    expect(data).toHaveProperty('reviews')
  })
})

describe('POST /api/spots/[id]/reviews', () => {
  beforeEach(() => vi.clearAllMocks())

  it('returns 401 when not authenticated', async () => {
    vi.mocked(getServerSession).mockResolvedValue(null)
    const res = await POST(
      new NextRequest('http://localhost', { method: 'POST', body: JSON.stringify({ rating: 5, body: 'Excelente local para voar!' }) }),
      { params: { id: 'spot-1' } }
    )
    expect(res.status).toBe(401)
  })

  it('returns 409 on duplicate review', async () => {
    vi.mocked(getServerSession).mockResolvedValue({ user: { id: 'u1', role: 'USER', email: 'x@x.com' } } as any)
    vi.mocked(prisma.review.findFirst).mockResolvedValue({ id: 'existing' } as any)
    const res = await POST(
      new NextRequest('http://localhost', { method: 'POST', body: JSON.stringify({ rating: 4, body: 'Gostei muito do local e da vista.' }) }),
      { params: { id: 'spot-1' } }
    )
    expect(res.status).toBe(409)
  })

  it('returns 201 for valid review', async () => {
    vi.mocked(getServerSession).mockResolvedValue({ user: { id: 'u1', role: 'USER', email: 'x@x.com' } } as any)
    vi.mocked(prisma.review.findFirst).mockResolvedValue(null)
    const res = await POST(
      new NextRequest('http://localhost', { method: 'POST', body: JSON.stringify({ rating: 5, body: 'Vista incrível, recomendo muito.' }) }),
      { params: { id: 'spot-1' } }
    )
    expect(res.status).toBe(201)
  })

  it('returns 422 for short body', async () => {
    vi.mocked(getServerSession).mockResolvedValue({ user: { id: 'u1', role: 'USER', email: 'x@x.com' } } as any)
    const res = await POST(
      new NextRequest('http://localhost', { method: 'POST', body: JSON.stringify({ rating: 3, body: 'Curto' }) }),
      { params: { id: 'spot-1' } }
    )
    expect(res.status).toBe(422)
  })
})
