import { motion } from 'framer-motion'
import { Check, MoreHorizontal, Brain, CheckCircle2 } from 'lucide-react'
import { useEffect, useRef, useState } from 'react'
import type { Exercise, Tick } from '@shared/types'
import { Icon } from '../lib/icon'
import { formatCountdown } from '../lib/format'
import { Switch } from './ui/Switch'
import { useT } from '../i18n'
import { useAnnounce } from '../lib/useAnnounce'

type Props = {
  exercise: Exercise
  tick?: Tick
  /** Сделано повторений сегодня (для daily-goal индикатора). */
  doneToday?: number
  onEdit: () => void
  onDelete: () => void
  onToggle: (enabled: boolean) => void
  onMarkDone: () => void
}

/**
 * iOS-flavoured exercise card. White surface, soft shadow, big readable
 * countdown. A subtle ring around the icon shows interval progress —
 * Apple Fitness ring spirit but minimalist.
 */
export function ExerciseCard({
  exercise,
  tick,
  doneToday,
  onEdit,
  onDelete,
  onToggle,
  onMarkDone
}: Props): JSX.Element {
  const ms = tick?.msUntilFire ?? exercise.nextFireAt - Date.now()
  const total = exercise.intervalMinutes * 60_000
  const remaining = Math.max(0, Math.min(total, ms))
  const elapsedPct = total > 0 ? 1 - remaining / total : 0
  const goalReached =
    exercise.dailyGoal !== undefined &&
    exercise.dailyGoal > 0 &&
    (doneToday ?? 0) >= exercise.dailyGoal
  // Если цель закрыта — упражнение «отдыхает» до завтра, isDue не считаем.
  const isDue = ms <= 0 && exercise.enabled && !goalReached
  const [menuOpen, setMenuOpen] = useState(false)
  const triggerRef = useRef<HTMLButtonElement>(null)
  const menuRef = useRef<HTMLDivElement>(null)

  // При открытии меню переводим фокус на первый пункт — клавиатурный
  // пользователь сразу внутри, без слепого Tab'а.
  useEffect(() => {
    if (!menuOpen) return
    menuRef.current
      ?.querySelector<HTMLButtonElement>('[role="menuitem"]')
      ?.focus()
  }, [menuOpen])

  // Esc закрывает и возвращает фокус на триггер; стрелки/Home/End — навигация.
  const onMenuKeyDown = (e: React.KeyboardEvent<HTMLDivElement>): void => {
    const items = Array.from(
      menuRef.current?.querySelectorAll<HTMLButtonElement>(
        '[role="menuitem"]'
      ) ?? []
    )
    if (items.length === 0) return
    const idx = items.indexOf(document.activeElement as HTMLButtonElement)
    if (e.key === 'Escape') {
      e.preventDefault()
      setMenuOpen(false)
      triggerRef.current?.focus()
    } else if (e.key === 'ArrowDown') {
      e.preventDefault()
      items[(idx + 1) % items.length]?.focus()
    } else if (e.key === 'ArrowUp') {
      e.preventDefault()
      items[(idx - 1 + items.length) % items.length]?.focus()
    } else if (e.key === 'Home') {
      e.preventDefault()
      items[0]?.focus()
    } else if (e.key === 'End') {
      e.preventDefault()
      items[items.length - 1]?.focus()
    }
  }
  // Дедуп rapid double-click на «Готово». Между кликом и обновлением
  // nextFireAt (через broadcastState) есть окно ~1 сек, в которое можно
  // вызвать markDone повторно и записать лишний entry в историю.
  const markDoneInFlightRef = useRef(false)
  const { t, lang } = useT()
  const announce = useAnnounce()
  const handleMarkDone = (): void => {
    if (markDoneInFlightRef.current) return
    markDoneInFlightRef.current = true
    onMarkDone()
    // Озвучиваем для screen-reader'ов — кнопка после засчёта исчезает,
    // визуальный feedback незрячему недоступен.
    announce(`${t('btn.done')}: ${exercise.name}`)
    // К моменту окончания таймаута isDue уже false (после store-tick), кнопка
    // не рендерится — флаг чистим на всякий случай для будущих кейсов.
    setTimeout(() => {
      markDoneInFlightRef.current = false
    }, 1000)
  }

  // Ring math
  const R = 22
  const C = 2 * Math.PI * R
  const dashOffset = C * (1 - elapsedPct)

  return (
    <motion.div
      layout
      initial={{ opacity: 0, y: 6 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, scale: 0.97 }}
      transition={{ type: 'spring', stiffness: 380, damping: 30 }}
      className="relative bg-surface rounded-3xl p-5 shadow-card dark:ring-0.5 dark:ring-hairline/30"
    >
      <div className="flex items-start gap-4">
        {/* Icon + progress ring */}
        <div className="relative w-14 h-14 shrink-0">
          <svg
            className="absolute inset-0 -rotate-90"
            viewBox="0 0 56 56"
            width="56"
            height="56"
          >
            <circle
              cx="28"
              cy="28"
              r={R}
              fill="none"
              strokeWidth="2.5"
              className="stroke-hairline/15 dark:stroke-hairline/30"
            />
            {exercise.enabled && (
              <circle
                cx="28"
                cy="28"
                r={R}
                fill="none"
                strokeWidth="2.5"
                strokeLinecap="round"
                strokeDasharray={C}
                strokeDashoffset={dashOffset}
                className={isDue ? 'stroke-accent' : 'stroke-accent/85'}
                style={{ transition: 'stroke-dashoffset 0.5s linear' }}
              />
            )}
          </svg>
          <div
            className={[
              'absolute inset-[8px] rounded-full grid place-items-center',
              exercise.enabled
                ? 'bg-accent/10 text-accent'
                : 'bg-surface-2 text-text/40'
            ].join(' ')}
          >
            <Icon name={exercise.icon} size={20} />
          </div>
        </div>

        <div className="flex-1 min-w-0">
          <div className="flex items-center justify-between gap-2">
            <h3 className="font-display text-[18px] font-bold leading-tight truncate">
              {exercise.name}
            </h3>
            <div className="relative">
              <button
                ref={triggerRef}
                onClick={() => setMenuOpen((v) => !v)}
                className="w-7 h-7 grid place-items-center rounded-full text-text/45 hover:bg-surface-2 active:scale-90 transition-all"
                aria-label={t('titlebar.menu_aria')}
                aria-haspopup="menu"
                aria-expanded={menuOpen}
              >
                <MoreHorizontal size={16} />
              </button>
              {menuOpen && (
                <>
                  <div
                    className="fixed inset-0 z-10"
                    onClick={() => setMenuOpen(false)}
                  />
                  <div
                    ref={menuRef}
                    role="menu"
                    aria-label={exercise.name}
                    onKeyDown={onMenuKeyDown}
                    className="absolute right-0 top-8 z-20 min-w-[140px] bg-surface rounded-xl shadow-sheet ring-0.5 ring-hairline/30 py-1 overflow-hidden"
                  >
                    <button
                      role="menuitem"
                      onClick={() => {
                        setMenuOpen(false)
                        onEdit()
                      }}
                      className="w-full text-left px-3 py-2 text-[13px] hover:bg-surface-2 active:bg-hairline/25"
                    >
                      {t('btn.edit')}
                    </button>
                    <button
                      role="menuitem"
                      onClick={() => {
                        setMenuOpen(false)
                        onDelete()
                      }}
                      className="w-full text-left px-3 py-2 text-[13px] text-destructive hover:bg-destructive/10 active:bg-destructive/15"
                    >
                      {t('btn.delete')}
                    </button>
                  </div>
                </>
              )}
            </div>
          </div>
          <div className="text-[14px] text-text/65 mt-1 font-medium">
            {t('editor.exercise.preview.meta', {
              reps: exercise.reps,
              min: exercise.intervalMinutes
            })}
          </div>

          {/* Countdown + switch */}
          <div className="flex items-end justify-between mt-3.5">
            <div>
              <div className="text-[12px] text-text/60 uppercase tracking-wider font-semibold inline-flex items-center gap-1">
                {goalReached ? (
                  <>
                    <CheckCircle2
                      size={11}
                      strokeWidth={2.5}
                      className="text-success"
                    />
                    {t('exercise.goal_reached.kicker')}
                  </>
                ) : isDue ? (
                  t('dashboard.stat.next.now')
                ) : (
                  t('fmt.through')
                )}
                {exercise.adaptive && !goalReached && (
                  <Brain
                    size={11}
                    strokeWidth={2.5}
                    className="text-info ml-0.5"
                    aria-label={t('exercise.adaptive.badge')}
                  />
                )}
              </div>
              <div
                className={[
                  'font-mono-num text-[24px] font-bold leading-none mt-1 tracking-tight',
                  goalReached
                    ? 'text-success'
                    : isDue
                      ? 'text-accent'
                      : 'text-text'
                ].join(' ')}
              >
                {!exercise.enabled
                  ? t('fmt.paused')
                  : goalReached
                    ? t('exercise.goal_reached.value', {
                        done: doneToday ?? 0,
                        goal: exercise.dailyGoal ?? 0
                      })
                    : formatCountdown(ms, lang)}
              </div>
            </div>
            <Switch
              checked={exercise.enabled}
              onChange={onToggle}
              aria-label={t('exercise.aria.toggle', { name: exercise.name })}
            />
          </div>
        </div>
      </div>

      {isDue && (
        <motion.button
          initial={{ opacity: 0, y: 4 }}
          animate={{ opacity: 1, y: 0 }}
          onClick={handleMarkDone}
          className="mt-4 w-full h-11 rounded-xl bg-accent text-white text-[15px] font-bold inline-flex items-center justify-center gap-1.5 active:scale-[0.98] transition-transform"
        >
          <Check size={15} strokeWidth={2.5} /> {t('btn.done')}
        </motion.button>
      )}
    </motion.div>
  )
}
