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

vi.mock('next/cache', () => ({ revalidatePath: vi.fn() }))
vi.mock('next/headers', () => ({
  cookies: vi.fn().mockResolvedValue({
    set: vi.fn(),
    get: vi.fn(),
    delete: vi.fn(),
  }),
}))
vi.mock('iron-session', () => ({
  getIronSession: vi.fn().mockResolvedValue({ userId: 'user-1', isDemo: false }),
}))
vi.mock('@/lib/session', () => ({
  sessionOptions: { cookieName: 'test', password: 'test' },
}))
vi.mock('@/lib/product-access', () => ({
  productAccessFilter: vi.fn().mockReturnValue({}),
}))
vi.mock('@/lib/prisma', () => ({
  prisma: {
    sprint: { findFirst: vi.fn() },
    product: { findFirst: vi.fn() },
    user: {
      findUnique: vi.fn(),
      update: vi.fn().mockResolvedValue({}),
    },
    $executeRaw: vi.fn().mockResolvedValue(1),
  },
}))

import { prisma } from '@/lib/prisma'
import { clearActiveSprintAction } from '@/actions/active-sprint'

const mockPrisma = prisma as unknown as {
  product: { findFirst: ReturnType<typeof vi.fn> }
  user: {
    findUnique: ReturnType<typeof vi.fn>
    update: ReturnType<typeof vi.fn>
  }
}

describe('clearActiveSprintAction', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('writes null instead of deleting the key', async () => {
    mockPrisma.product.findFirst.mockResolvedValueOnce({ id: 'p1' })
    mockPrisma.user.findUnique.mockResolvedValueOnce({
      settings: { layout: { activeSprints: { p1: 'sprint-1', p2: 'sprint-2' } } },
    })

    const result = await clearActiveSprintAction('p1')

    expect(result).toEqual({ success: true })
    const updateArg = mockPrisma.user.update.mock.calls[0][0] as {
      data: { settings: { layout?: { activeSprints?: Record<string, string | null> } } }
    }
    expect(updateArg.data.settings.layout?.activeSprints).toEqual({
      p1: null,
      p2: 'sprint-2',
    })
  })

  it('preserves other product keys when clearing one', async () => {
    mockPrisma.product.findFirst.mockResolvedValueOnce({ id: 'p1' })
    mockPrisma.user.findUnique.mockResolvedValueOnce({
      settings: {
        layout: {
          activeSprints: { p1: 'sprint-1', p2: 'sprint-2', p3: null },
        },
      },
    })

    await clearActiveSprintAction('p1')

    const updateArg = mockPrisma.user.update.mock.calls[0][0] as {
      data: { settings: { layout?: { activeSprints?: Record<string, string | null> } } }
    }
    expect(updateArg.data.settings.layout?.activeSprints).toEqual({
      p1: null,
      p2: 'sprint-2',
      p3: null,
    })
  })

  it('rejects when product is not accessible', async () => {
    mockPrisma.product.findFirst.mockResolvedValueOnce(null)

    const result = await clearActiveSprintAction('p1')

    expect(result).toEqual({ error: 'Product niet gevonden of niet toegankelijk' })
    expect(mockPrisma.user.update).not.toHaveBeenCalled()
  })

  it('rejects invalid productId', async () => {
    const result = await clearActiveSprintAction('')

    expect(result).toEqual({ error: 'Ongeldig product-id' })
    expect(mockPrisma.user.update).not.toHaveBeenCalled()
  })
})
