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

const { mockGetSession } = vi.hoisted(() => ({ mockGetSession: vi.fn() }))

vi.mock('@/lib/auth', () => ({
  getSession: mockGetSession,
}))

vi.mock('@/lib/prisma', () => ({
  prisma: {
    product: { findMany: vi.fn() },
    claudeQuestion: { findMany: vi.fn() },
    idea: { findMany: vi.fn().mockResolvedValue([]) },
  },
}))

vi.mock('@/lib/product-access', () => ({
  productAccessFilter: vi.fn().mockReturnValue({}),
  getAccessibleProduct: vi.fn(),
}))

import { prisma } from '@/lib/prisma'
import type { NextRequest } from 'next/server'
import { GET } from '@/app/api/realtime/notifications/route'

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

function makeReq(): NextRequest {
  // Minimaal NextRequest-shape voor de auth-pad — we komen niet bij de
  // pg-stream-setup omdat de auth-fail vóór dat punt gebeurt.
  return { signal: new AbortController().signal } as unknown as NextRequest
}

beforeEach(() => {
  vi.clearAllMocks()
})

import { productAccessFilter } from '@/lib/product-access'

const mockProductAccessFilter = productAccessFilter as ReturnType<typeof vi.fn>

describe('GET /api/realtime/notifications', () => {
  it('401 zonder iron-session cookie, geen DB-call', async () => {
    mockGetSession.mockResolvedValue({ userId: undefined, isDemo: false })
    const res = await GET(makeReq())
    expect(res.status).toBe(401)
    expect(mockPrisma.product.findMany).not.toHaveBeenCalled()
  })

  it('access-isolation: productAccessFilter wordt met de juiste userId aangeroepen', async () => {
    // ST-1106: cross-product-isolatie zit in de productAccessFilter-Set die we
    // bij connect opbouwen. We mocken de filter zodat product.findMany wel
    // aangeroepen wordt maar geen producten retourneert; daarna stoppen we
    // vóór de pg-stream-setup (DIRECT_URL ontbreekt → 500).
    mockGetSession.mockResolvedValue({ userId: 'user-A', isDemo: false })
    mockProductAccessFilter.mockReturnValue({ user_id: 'user-A' })
    mockPrisma.product.findMany.mockResolvedValue([])

    // We laten de stream zelf falen door DIRECT_URL/DATABASE_URL niet te zetten.
    const before = { ...process.env }
    delete process.env.DIRECT_URL
    delete process.env.DATABASE_URL
    try {
      const res = await GET(makeReq())
      expect(res.status).toBe(500)
    } finally {
      process.env.DIRECT_URL = before.DIRECT_URL
      process.env.DATABASE_URL = before.DATABASE_URL
    }

    // De filter is met de echte userId aangeroepen (cross-user lekt niet)
    expect(mockProductAccessFilter).toHaveBeenCalledWith('user-A')
    expect(mockPrisma.product.findMany).toHaveBeenCalledWith({
      where: { archived: false, user_id: 'user-A' },
      select: { id: true },
    })
  })
})

// Solo-route filter (entity='question' uitgesloten) is een 1-regel-fix in
// app/api/realtime/solo/route.ts. Visueel reviewbaar in de diff; full-stream-
// regressie wordt handmatig gedekt in ST-1108-acceptatie.
