import { describe, it, expect, vi, beforeEach } from 'vitest'

vi.mock('@/lib/prisma', () => ({
  prisma: {
    product: {
      findMany: vi.fn(),
    },
  },
}))

vi.mock('@/lib/api-auth', () => ({
  authenticateApiRequest: vi.fn(),
}))

import { prisma } from '@/lib/prisma'
import { authenticateApiRequest } from '@/lib/api-auth'
import { GET as getProducts } from '@/app/api/products/route'

const mockPrisma = prisma as unknown as {
  product: { findMany: ReturnType<typeof vi.fn> }
}
const mockAuth = authenticateApiRequest as ReturnType<typeof vi.fn>

function makeRequest(): Request {
  return new Request('http://localhost/api/products', {
    method: 'GET',
    headers: { Authorization: 'Bearer test-token' },
  })
}

describe('GET /api/products', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockAuth.mockResolvedValue({ userId: 'user-1', isDemo: false })
  })

  // TC-P-04
  it('returns products owned by the authenticated user', async () => {
    mockPrisma.product.findMany.mockResolvedValue([
      { id: 'prod-1', name: 'Alpha', repo_url: null },
      { id: 'prod-2', name: 'Beta', repo_url: 'https://github.com/example/beta' },
    ])

    const res = await getProducts(makeRequest())
    const data = await res.json()

    expect(res.status).toBe(200)
    expect(data).toHaveLength(2)
    expect(data[0]).toMatchObject({ id: 'prod-1', name: 'Alpha' })
    expect(data[1]).toMatchObject({ id: 'prod-2', name: 'Beta' })
  })

  // TC-P-05
  it('includes products where the user is a team member via productAccessFilter', async () => {
    mockPrisma.product.findMany.mockResolvedValue([
      { id: 'prod-shared', name: 'Shared Product', repo_url: null },
    ])

    const res = await getProducts(makeRequest())
    const data = await res.json()

    expect(res.status).toBe(200)
    expect(data).toHaveLength(1)
    expect(mockPrisma.product.findMany).toHaveBeenCalledWith(
      expect.objectContaining({
        where: expect.objectContaining({
          archived: false,
          OR: expect.arrayContaining([
            { user_id: 'user-1' },
            { members: { some: { user_id: 'user-1' } } },
          ]),
        }),
      })
    )
  })

  // TC-P-06
  it('returns empty array when user has no products', async () => {
    mockPrisma.product.findMany.mockResolvedValue([])

    const res = await getProducts(makeRequest())
    const data = await res.json()

    expect(res.status).toBe(200)
    expect(data).toEqual([])
  })

  // TC-P-07
  it('excludes archived products by querying with archived: false', async () => {
    mockPrisma.product.findMany.mockResolvedValue([
      { id: 'prod-active', name: 'Active', repo_url: null },
    ])

    const res = await getProducts(makeRequest())

    expect(res.status).toBe(200)
    expect(mockPrisma.product.findMany).toHaveBeenCalledWith(
      expect.objectContaining({
        where: expect.objectContaining({ archived: false }),
      })
    )
  })
})
