import type {
  BumperTemplateDto,
  GroupSummaryDto,
  JunctionElementDto,
  JunctionElementKind,
} from '@/shared/api/types'

/** Заставка без загруженного звука синтезируется фиксированной длины — та же цифра, что на сервере. */
export const DEFAULT_BUMPER_SECONDS = 8

export const KIND_COLORS: Record<JunctionElementKind, string> = {
  Ad: 'bg-amber-500/70',
  Promo: 'bg-sky-500/70',
  Bumper: 'bg-violet-500/70',
  Filler: 'bg-muted-foreground/40',
}

/**
 * Звено цепочки: либо одиночная врезка, либо развилка — несколько врезок с одной меткой, из
 * которых в эфир идёт одна. Развилка занимает одно место в цепочке, поэтому и рисуется одним.
 */
export type ChainStep = {
  key: string
  choiceKey: string | null
  elements: JunctionElementDto[]
}

/** Группирует врезки в звенья по метке развилки; порядок сохраняется (сервер держит их подряд). */
export function toSteps(elements: JunctionElementDto[]): ChainStep[] {
  const steps: ChainStep[] = []
  for (const element of [...elements].sort((a, b) => a.position - b.position)) {
    const last = steps.at(-1)
    if (element.choiceKey && last?.choiceKey === element.choiceKey) {
      last.elements.push(element)
      continue
    }
    steps.push({
      key: element.choiceKey ?? element.id,
      choiceKey: element.choiceKey,
      elements: [element],
    })
  }
  return steps
}

/**
 * Прикидка длины врезки для линейки. По длительности — точная, по количеству — среднее единицы
 * группы: в смешанной группе «одна единица» это то ли ролик, то ли блок, поэтому число заведомо
 * приблизительное и помечается как оценка.
 */
export function estimateSeconds(
  element: JunctionElementDto,
  groups: GroupSummaryDto[] | undefined,
  bumpers: BumperTemplateDto[] | undefined,
): { seconds: number; exact: boolean } {
  if (element.kind === 'Bumper') {
    const template = bumpers?.find((b) => b.id === element.bumperTemplateId)
    return { seconds: template?.audioDurationSeconds ?? DEFAULT_BUMPER_SECONDS, exact: true }
  }
  if (element.amountMode === 'Duration') return { seconds: element.amountValue * 60, exact: true }

  const group = groups?.find((g) => g.id === element.groupId)
  if (!group || group.unitCount === 0) return { seconds: 0, exact: false }
  return {
    seconds: (element.amountValue * group.totalDurationSeconds) / group.unitCount,
    exact: false,
  }
}

/** Длина звена: у развилки — средняя по весам, потому что в эфир пойдёт одна из врезок. */
export function stepSeconds(
  step: ChainStep,
  groups: GroupSummaryDto[] | undefined,
  bumpers: BumperTemplateDto[] | undefined,
): { seconds: number; exact: boolean } {
  const parts = step.elements.map((e) => ({
    ...estimateSeconds(e, groups, bumpers),
    weight: Math.max(0, e.choiceWeight),
  }))
  if (parts.length === 1) return { seconds: parts[0].seconds, exact: parts[0].exact }

  const total = parts.reduce((sum, p) => sum + p.weight, 0)
  const seconds =
    total > 0
      ? parts.reduce((sum, p) => sum + (p.seconds * p.weight) / total, 0)
      : parts.reduce((sum, p) => sum + p.seconds, 0) / parts.length
  // У развилки точной длины нет по определению: жребий решает в момент генерации.
  return { seconds, exact: false }
}

/** Доля врезки в развилке в процентах — иначе «иногда так, иногда эдак» невозможно прочитать. */
export function choicePercent(step: ChainStep, element: JunctionElementDto) {
  const total = step.elements.reduce((sum, e) => sum + Math.max(0, e.choiceWeight), 0)
  if (total <= 0) return Math.round(100 / step.elements.length)
  return Math.round((Math.max(0, element.choiceWeight) / total) * 100)
}
