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

const { mockStoryCount, mockTaskCount, mockTaskFindMany } = vi.hoisted(() => ({
  mockStoryCount: vi.fn(),
  mockTaskCount: vi.fn(),
  mockTaskFindMany: vi.fn(),
}))

vi.mock('@/lib/prisma', () => ({
  prisma: {
    story: { count: mockStoryCount },
    task: { count: mockTaskCount, findMany: mockTaskFindMany },
  },
}))

vi.mock('@/lib/product-access', () => ({
  productAccessFilter: () => ({ some: 'filter' }),
}))

import { getBacklogHealth } from '@/lib/insights/backlog-health'

function makeTask(id: string, daysAgo: number) {
  const updatedAt = new Date(Date.now() - daysAgo * 86_400_000)
  return {
    id,
    title: `Task ${id}`,
    updated_at: updatedAt,
    story: {
      product: { id: 'prod-1', name: 'My Product' },
      sprint: { sprint_goal: 'Sprint goal' },
    },
  }
}

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

describe('getBacklogHealth', () => {
  it('returns all zeros when backlog is healthy', async () => {
    mockStoryCount.mockResolvedValue(0)
    mockTaskCount.mockResolvedValue(0)
    mockTaskFindMany.mockResolvedValue([])

    const result = await getBacklogHealth('user-1')

    expect(result.storiesWithoutAc).toBe(0)
    expect(result.tasksWithoutPlan).toBe(0)
    expect(result.stuckTasks).toEqual([])
  })

  it('returns counts and stuck tasks when everything is flagged', async () => {
    mockStoryCount.mockResolvedValue(5)
    mockTaskCount.mockResolvedValue(3)
    mockTaskFindMany.mockResolvedValue([makeTask('t1', 10), makeTask('t2', 8)])

    const result = await getBacklogHealth('user-1')

    expect(result.storiesWithoutAc).toBe(5)
    expect(result.tasksWithoutPlan).toBe(3)
    expect(result.stuckTasks).toHaveLength(2)
    expect(result.stuckTasks[0].taskId).toBe('t1')
    expect(result.stuckTasks[0].daysStuck).toBeGreaterThanOrEqual(10)
    expect(result.stuckTasks[0].productName).toBe('My Product')
    expect(result.stuckTasks[0].sprintGoal).toBe('Sprint goal')
  })

  it('mixed: some counters non-zero, one stuck task, no sprint', async () => {
    mockStoryCount.mockResolvedValue(2)
    mockTaskCount.mockResolvedValue(0)
    const task = makeTask('t3', 14)
    task.story.sprint = null as unknown as { sprint_goal: string }
    mockTaskFindMany.mockResolvedValue([task])

    const result = await getBacklogHealth('user-1')

    expect(result.storiesWithoutAc).toBe(2)
    expect(result.tasksWithoutPlan).toBe(0)
    expect(result.stuckTasks[0].sprintGoal).toBeNull()
    expect(result.stuckTasks[0].daysStuck).toBeGreaterThanOrEqual(14)
  })
})
