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

export interface BurndownDay {
  day: string
  remaining: number
  ideal: number
}

export interface BurndownSprint {
  sprintId: string
  sprintCode: string
  productId: string
  productName: string
  sprintGoal: string
  days: BurndownDay[]
}

const DAY_MS = 86_400_000

function toUTCMidnight(d: Date): Date {
  return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()))
}

export function computeBurndownDays(
  tasks: { status: string; updated_at: Date }[],
  startDate: Date,
  endDate: Date,
): BurndownDay[] {
  const start = toUTCMidnight(startDate)
  const end = toUTCMidnight(endDate)
  const total = tasks.length
  // n = number of intervals (end - start in days)
  const n = Math.round((end.getTime() - start.getTime()) / DAY_MS)

  const days: BurndownDay[] = []

  for (let i = 0; ; i++) {
    const dayStart = new Date(start.getTime() + i * DAY_MS)
    if (dayStart > end) break

    const nextDay = new Date(dayStart.getTime() + DAY_MS)
    const done = tasks.filter(t => t.status === 'DONE' && t.updated_at < nextDay).length
    const ideal = n === 0 ? 0 : Math.round((total * (n - i) / n) * 100) / 100

    days.push({
      day: dayStart.toISOString().slice(0, 10),
      remaining: total - done,
      ideal,
    })
  }

  return days
}

export async function getBurndownData(userId: string): Promise<BurndownSprint[]> {
  const now = new Date()

  const sprints = await prisma.sprint.findMany({
    where: {
      status: 'OPEN',
      product: productAccessFilter(userId),
    },
    select: {
      id: true,
      code: true,
      sprint_goal: true,
      created_at: true,
      completed_at: true,
      product: { select: { id: true, name: true } },
      tasks: { select: { status: true, updated_at: true } },
    },
  })

  return sprints
    .map(sprint => {
      const endDate = sprint.completed_at ?? now
      if (endDate <= sprint.created_at) return null

      return {
        sprintId: sprint.id,
        sprintCode: sprint.code,
        productId: sprint.product.id,
        productName: sprint.product.name,
        sprintGoal: sprint.sprint_goal,
        days: computeBurndownDays(sprint.tasks, sprint.created_at, endDate),
      }
    })
    .filter((s): s is BurndownSprint => s !== null)
}
