import { Anchor, Plus } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import type { GridLayerDto, ScheduleTemplateDto, SlotDto } from '@/shared/api/types'
import { Button } from '@/shared/ui/button'
import { cn } from '@/shared/lib/cn'

const HOUR_HEIGHT = 44
const WEEKDAYS = [1, 2, 3, 4, 5, 6, 0]

/** Цвет блока — по дейпарту: сетка должна читаться одним взглядом, без легенды. */
const DAYPART_CLASS: Record<string, string> = {
  Morning: 'bg-amber-500/20 border-amber-500/40',
  Day: 'bg-sky-500/20 border-sky-500/40',
  Prime: 'bg-violet-500/25 border-violet-500/50',
  Night: 'bg-slate-500/20 border-slate-500/40',
}

function minutesOf(time: string): number {
  const [h, m] = time.split(':')
  return Number(h) * 60 + Number(m)
}

/**
 * Смещение слота от начала вещательных суток. Ночной блок (00:00–06:00 при старте суток в 06:00)
 * принадлежит предыдущему дню, поэтому его смещение больше суточного, а не отрицательное.
 */
function offsetInDay(slotStart: string, dayStart: string): number {
  const diff = minutesOf(slotStart) - minutesOf(dayStart)
  return diff >= 0 ? diff : diff + 24 * 60
}

/** Слоты, попадающие в колонку дня: слот без дня недели идёт каждый день. */
function slotsOfDay(layers: GridLayerDto[], weekday: number) {
  return layers
    .filter((layer) => layer.isEnabled)
    .flatMap((layer) =>
      layer.slots
        .filter((slot) => slot.weekday === null || slot.weekday === weekday)
        .map((slot) => ({ slot, layer })),
    )
}

export function ScheduleGrid({
  template,
  selectedSlotId,
  onSelectSlot,
  onAddSlot,
}: {
  template: ScheduleTemplateDto
  selectedSlotId: string | null
  onSelectSlot: (slot: SlotDto) => void
  onAddSlot: (weekday: number, startMinutes: number) => void
}) {
  const { t } = useTranslation()
  const dayStart = template.dayStartTime.slice(0, 5)
  const dayStartMinutes = minutesOf(dayStart)

  // Подписи часов идут от начала вещательных суток, а не от полуночи.
  const hours = Array.from({ length: 24 }, (_, i) => (dayStartMinutes / 60 + i) % 24)

  // Слои отсортированы по убыванию приоритета: слот, лежащий под более приоритетным, штрихуем.
  const ordered = [...template.layers].sort((a, b) => b.priority - a.priority)

  const isCovered = (slot: SlotDto, layer: GridLayerDto, weekday: number) => {
    const from = offsetInDay(slot.targetStart, dayStart)
    const to = from + slot.targetDurationMinutes
    return ordered
      .filter((other) => other.isEnabled && other.priority > layer.priority)
      .some((other) =>
        other.slots
          .filter((s) => s.weekday === null || s.weekday === weekday)
          .some((s) => {
            const otherFrom = offsetInDay(s.targetStart, dayStart)
            return from < otherFrom + s.targetDurationMinutes && otherFrom < to
          }),
      )
  }

  return (
    <div className="crt-panel overflow-x-auto rounded-md">
      <div className="min-w-[720px]">
        <div className="grid grid-cols-[56px_repeat(7,1fr)] border-b border-border text-xs text-muted-foreground">
          <div className="px-2 py-1">{dayStart}</div>
          {WEEKDAYS.map((weekday) => (
            <div key={weekday} className="px-2 py-1 text-center font-medium">
              {t(`admin.channels.weekdays.${weekday}`)}
            </div>
          ))}
        </div>

        <div className="grid grid-cols-[56px_repeat(7,1fr)]">
          <div>
            {hours.map((hour, index) => (
              <div
                key={index}
                className="border-b border-border/40 px-2 text-[11px] text-muted-foreground"
                style={{ height: HOUR_HEIGHT }}
              >
                {hour.toString().padStart(2, '0')}:00
              </div>
            ))}
          </div>

          {WEEKDAYS.map((weekday) => (
            <div
              key={weekday}
              className="relative border-l border-border"
              style={{ height: HOUR_HEIGHT * 24 }}
            >
              {hours.map((_, index) => (
                <button
                  key={index}
                  type="button"
                  title={t('admin.channels.addSlotHere')}
                  className="group absolute inset-x-0 border-b border-border/40 hover:bg-muted/30"
                  style={{ top: HOUR_HEIGHT * index, height: HOUR_HEIGHT }}
                  onClick={() => onAddSlot(weekday, (dayStartMinutes + index * 60) % (24 * 60))}
                >
                  <Plus className="mx-auto h-3 w-3 opacity-0 group-hover:opacity-40" />
                </button>
              ))}

              {slotsOfDay(ordered, weekday).map(({ slot, layer }) => {
                const from = offsetInDay(slot.targetStart, dayStart)
                const covered = isCovered(slot, layer, weekday)
                return (
                  <button
                    key={`${slot.id}-${weekday}`}
                    type="button"
                    onClick={() => onSelectSlot(slot)}
                    className={cn(
                      'absolute inset-x-1 overflow-hidden rounded border px-1.5 py-0.5 text-left text-[11px] leading-tight',
                      DAYPART_CLASS[slot.daypart] ?? DAYPART_CLASS.Day,
                      selectedSlotId === slot.id && 'ring-2 ring-primary',
                      // Перекрытый слот виден, но приглушён: он не сыграет, пока лежит под старшим слоем.
                      covered && 'opacity-40 [background-image:repeating-linear-gradient(45deg,transparent,transparent_4px,rgba(0,0,0,.15)_4px,rgba(0,0,0,.15)_8px)]',
                    )}
                    style={{
                      top: (from / 60) * HOUR_HEIGHT,
                      height: Math.max(16, (slot.targetDurationMinutes / 60) * HOUR_HEIGHT - 2),
                    }}
                  >
                    <span className="flex items-center gap-1 font-medium">
                      {slot.isAnchor && <Anchor className="h-3 w-3 shrink-0" />}
                      {slot.targetStart.slice(0, 5)}
                    </span>
                    <span className="block truncate">{slot.title}</span>
                  </button>
                )
              })}
            </div>
          ))}
        </div>
      </div>
    </div>
  )
}

/** Панель слоёв: видимость, приоритет и выбор редактируемого. */
export function LayerList({
  template,
  activeLayerId,
  onSelect,
  onDelete,
}: {
  template: ScheduleTemplateDto
  activeLayerId: string | null
  onSelect: (layer: GridLayerDto) => void
  onDelete: (layer: GridLayerDto) => void
}) {
  const { t } = useTranslation()
  const ordered = [...template.layers].sort((a, b) => b.priority - a.priority)

  return (
    <ul className="divide-y divide-border text-sm">
      {ordered.map((layer) => (
        <li key={layer.id} className="flex items-center gap-2 py-1.5">
          <button
            type="button"
            className={cn(
              'min-w-0 flex-1 truncate text-left',
              activeLayerId === layer.id && 'text-primary',
            )}
            onClick={() => onSelect(layer)}
          >
            {layer.name}
          </button>
          <span className="shrink-0 text-xs text-muted-foreground">
            {layer.isBackground ? t('admin.channels.background') : layer.priority}
          </span>
          <span className="shrink-0 text-xs text-muted-foreground">
            {layer.slots.length}
          </span>
          {!layer.isBackground && (
            <Button size="sm" variant="ghost" onClick={() => onDelete(layer)}>
              ×
            </Button>
          )}
        </li>
      ))}
    </ul>
  )
}
