import type { AgendaEvent } from "./agenda-types.ts"

export interface PositionedEvent {
  event: AgendaEvent
  /** Minutes depuis minuit. */
  top: number
  /** Durée en minutes (minimum appliqué côté rendu). */
  duration: number
  leftPct: number
  widthPct: number
}

interface WorkItem {
  event: AgendaEvent
  startMin: number
  endMin: number
  col: number
  cluster: number
}

/**
 * Positionne les événements horaires d'une colonne jour façon Google Calendar :
 * les événements qui se chevauchent se partagent la largeur par colonnes.
 */
export function layoutDayEvents(events: AgendaEvent[], day: Date): PositionedEvent[] {
  const dayStart = new Date(day)
  dayStart.setHours(0, 0, 0, 0)
  const dayStartMs = dayStart.getTime()
  const minutesInDay = 24 * 60

  const items: WorkItem[] = events
    .map((event) => {
      const startMin = Math.max(0, (event.start.getTime() - dayStartMs) / 60000)
      const endMin = Math.min(minutesInDay, (event.end.getTime() - dayStartMs) / 60000)
      return { event, startMin, endMin: Math.max(endMin, startMin + 15), col: 0, cluster: 0 }
    })
    .filter((it) => it.startMin < minutesInDay && it.endMin > 0)
    .sort((a, b) => a.startMin - b.startMin || b.endMin - a.endMin)

  // Regroupe en clusters d'événements transitivement chevauchants.
  let clusterId = 0
  let clusterEnd = -1
  for (const it of items) {
    if (it.startMin >= clusterEnd) {
      clusterId++
      clusterEnd = it.endMin
    } else {
      clusterEnd = Math.max(clusterEnd, it.endMin)
    }
    it.cluster = clusterId
  }

  const positioned: PositionedEvent[] = []
  const clusters = new Map<number, WorkItem[]>()
  for (const it of items) {
    const list = clusters.get(it.cluster) ?? []
    list.push(it)
    clusters.set(it.cluster, list)
  }

  for (const list of clusters.values()) {
    // Attribution gloutonne de colonnes.
    const colEnds: number[] = []
    for (const it of list) {
      let col = colEnds.findIndex((end) => end <= it.startMin)
      if (col === -1) {
        col = colEnds.length
        colEnds.push(it.endMin)
      } else {
        colEnds[col] = it.endMin
      }
      it.col = col
    }
    const colCount = colEnds.length
    const width = 100 / colCount
    for (const it of list) {
      positioned.push({
        event: it.event,
        top: it.startMin,
        duration: it.endMin - it.startMin,
        leftPct: it.col * width,
        // Léger débord à la Google quand il reste de la place à droite.
        widthPct: it.col === colCount - 1 ? width : Math.min(width * 1.7, 100 - it.col * width),
      })
    }
  }

  return positioned.sort((a, b) => a.top - b.top)
}
