/**
 * Conflict Detection Service
 *
 * Pure utility for detecting scheduling conflicts in a YouTube
 * content calendar. Checks for same-day collisions, weekly frequency
 * limits, and weekend scheduling.
 */

import { parseISO, startOfWeek } from 'date-fns'

export interface CalendarEvent {
  id: number
  channelId: number
  scheduledDate: string // ISO date
  contentType: 'short' | 'longform' | 'premiere'
  seriesId?: number
  seriesOrder?: number
}

export interface Conflict {
  type: 'same_day' | 'frequency_exceeded' | 'series_order' | 'weekend'
  message: string
  eventIds: number[]
  severity: 'warning' | 'error'
}

interface ScheduleConfig {
  longformPerWeek: number
  shortsPerWeek: number
}

function groupBy<T>(items: T[], keyFn: (item: T) => string): Map<string, T[]> {
  const map = new Map<string, T[]>()
  for (const item of items) {
    const key = keyFn(item)
    const group = map.get(key) ?? []
    group.push(item)
    map.set(key, group)
  }
  return map
}

function detectSameDayConflicts(events: CalendarEvent[]): Conflict[] {
  const conflicts: Conflict[] = []
  const byDayChannel = groupBy(
    events,
    (e) => `${e.channelId}-${e.scheduledDate.split('T')[0]}`,
  )

  for (const [, dayEvents] of byDayChannel) {
    const longforms = dayEvents.filter((e) => e.contentType === 'longform')
    if (longforms.length > 1) {
      conflicts.push({
        type: 'same_day',
        message: `${longforms.length} Longform-Videos am selben Tag geplant`,
        eventIds: longforms.map((e) => e.id),
        severity: 'error',
      })
    }
  }

  return conflicts
}

function detectFrequencyConflicts(
  events: CalendarEvent[],
  schedule: ScheduleConfig,
): Conflict[] {
  const conflicts: Conflict[] = []
  const byWeekChannel = groupBy(events, (e) => {
    const weekStart = startOfWeek(parseISO(e.scheduledDate), { weekStartsOn: 1 })
    return `${e.channelId}-${weekStart.toISOString()}`
  })

  for (const [, weekEvents] of byWeekChannel) {
    const longforms = weekEvents.filter((e) => e.contentType === 'longform')
    const shorts = weekEvents.filter((e) => e.contentType === 'short')

    if (longforms.length > schedule.longformPerWeek) {
      conflicts.push({
        type: 'frequency_exceeded',
        message: `${longforms.length}/${schedule.longformPerWeek} Longform-Videos diese Woche`,
        eventIds: longforms.map((e) => e.id),
        severity: 'warning',
      })
    }

    if (shorts.length > schedule.shortsPerWeek) {
      conflicts.push({
        type: 'frequency_exceeded',
        message: `${shorts.length}/${schedule.shortsPerWeek} Shorts diese Woche`,
        eventIds: shorts.map((e) => e.id),
        severity: 'warning',
      })
    }
  }

  return conflicts
}

function detectWeekendConflicts(events: CalendarEvent[]): Conflict[] {
  const conflicts: Conflict[] = []

  for (const event of events) {
    const dayOfWeek = parseISO(event.scheduledDate).getDay()
    if (dayOfWeek === 0 || dayOfWeek === 6) {
      conflicts.push({
        type: 'weekend',
        message: 'Video am Wochenende geplant',
        eventIds: [event.id],
        severity: 'warning',
      })
    }
  }

  return conflicts
}

function detectConflicts(events: CalendarEvent[], schedule: ScheduleConfig): Conflict[] {
  return [
    ...detectSameDayConflicts(events),
    ...detectFrequencyConflicts(events, schedule),
    ...detectWeekendConflicts(events),
  ]
}

export { detectConflicts }
