import { useState, useCallback, useEffect, useRef, useMemo } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { useNavigate } from '@tanstack/react-router'
import { cn } from '@/lib/utils'
import { useAuthStore } from '@/store/auth-store'
import {
  fetchFlashcardTerms,
  fetchUserProgress,
  upsertTermProgress,
  startSession,
  endSession,
  logReview,
  fetchFlashcardLists,
} from '../api/flashcard-api'
import type { FlashcardTerm, UserProgress } from '../api/flashcard-api'
import { EASE, type EaseKey } from '../lib/srs-intervals'

interface Props {
  listId: number
}

type SessionStats = { known: number; learning: number; ignored: number }

function speak(word: string) {
  try {
    const u = new SpeechSynthesisUtterance(word)
    u.lang = 'en-US'
    u.rate = 0.9
    speechSynthesis.cancel()
    speechSynthesis.speak(u)
  } catch { /* noop */ }
}

export function FlashCardLearnPage({ listId }: Props) {
  const navigate = useNavigate()
  const user = useAuthStore(s => s.user)
  const queryClient = useQueryClient()

  const [isFlipped, setIsFlipped] = useState(false)
  const [currentIdx, setCurrentIdx] = useState(0)
  const [sessionStats, setSessionStats] = useState<SessionStats>({ known: 0, learning: 0, ignored: 0 })
  const [isDone, setIsDone] = useState(false)
  const [fx, setFx] = useState<'known' | 'review' | null>(null)

  // Bookmarks — per-list, persisted in localStorage
  const bookmarkKey = `flashcard-bookmarks-${listId}`
  const [bookmarks, setBookmarks] = useState<Set<number>>(() => {
    try {
      const raw = localStorage.getItem(bookmarkKey)
      return raw ? new Set<number>(JSON.parse(raw)) : new Set()
    } catch { return new Set() }
  })
  const toggleBookmark = useCallback((termId: number) => {
    setBookmarks(prev => {
      const next = new Set(prev)
      if (next.has(termId)) next.delete(termId)
      else next.add(termId)
      try { localStorage.setItem(bookmarkKey, JSON.stringify([...next])) } catch { /* noop */ }
      return next
    })
  }, [bookmarkKey])

  // Refs for unmount cleanup so effects see fresh values
  const sessionIdRef = useRef<number | null>(null)
  const statsRef = useRef<SessionStats>(sessionStats)
  const isDoneRef = useRef(false)
  const newTermIdsAtStartRef = useRef<Set<number>>(new Set())
  const answeredNewIdsRef = useRef<Set<number>>(new Set())

  useEffect(() => { statsRef.current = sessionStats }, [sessionStats])
  useEffect(() => { isDoneRef.current = isDone }, [isDone])

  const { data: terms = [], isLoading: loadingTerms } = useQuery({
    queryKey: ['flashcard-terms', listId],
    queryFn: () => fetchFlashcardTerms(listId),
  })

  const { data: lists = [] } = useQuery({
    queryKey: ['flashcard-lists'],
    queryFn: fetchFlashcardLists,
    staleTime: 5 * 60 * 1000,
  })
  const currentList = lists.find(l => l.id === listId)

  const { data: progress = [] } = useQuery({
    queryKey: ['flashcard-progress', user?.id, listId],
    queryFn: () => fetchUserProgress(user!.id, listId),
    enabled: !!user,
  })

  const progressMap = useMemo(() => {
    const m: Record<number, UserProgress> = {}
    progress.forEach(p => { m[p.term_id] = p })
    return m
  }, [progress])

  // Session term ordering: prioritise due-for-review, then new, then known
  const sessionTerms: FlashcardTerm[] = useMemo(() => {
    if (!terms.length) return []
    const now = Date.now()
    const due: FlashcardTerm[] = []
    const fresh: FlashcardTerm[] = []
    const known: FlashcardTerm[] = []
    for (const t of terms) {
      const p = progressMap[t.id]
      if (p?.status === 'ignored') continue
      if (!p) { fresh.push(t); continue }
      if (!p.next_review_at) { fresh.push(t); continue }
      if (new Date(p.next_review_at).getTime() <= now) { due.push(t); continue }
      if (p.status === 'known') known.push(t)
      else fresh.push(t)
    }
    return [...due, ...fresh, ...known]
  }, [terms, progressMap])

  // Snapshot "new" term IDs at session start (runs once when data is loaded)
  useEffect(() => {
    if (newTermIdsAtStartRef.current.size === 0 && terms.length > 0) {
      const newIds = new Set<number>()
      for (const t of terms) {
        const s = progressMap[t.id]?.status ?? 'new'
        if (s === 'new') newIds.add(t.id)
      }
      newTermIdsAtStartRef.current = newIds
    }
  }, [terms, progressMap])

  // Start session on mount (guarded against StrictMode double-invoke)
  useEffect(() => {
    if (!user || sessionIdRef.current !== null) return
    let cancelled = false
    startSession(user.id, listId)
      .then(s => { if (!cancelled) sessionIdRef.current = s.id })
      .catch(err => console.error('startSession failed:', err))
    return () => { cancelled = true }
  }, [user, listId])

  // End session on unmount (if not already ended via done-screen effect)
  useEffect(() => {
    return () => {
      const sid = sessionIdRef.current
      if (sid === null || isDoneRef.current) return
      const s = statsRef.current
      const reviewed = s.known + s.learning + s.ignored
      endSession(sid, reviewed, answeredNewIdsRef.current.size)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  // End session when reaching done screen
  useEffect(() => {
    if (!isDone) return
    const sid = sessionIdRef.current
    if (sid === null) return
    const s = statsRef.current
    const reviewed = s.known + s.learning + s.ignored
    endSession(sid, reviewed, answeredNewIdsRef.current.size)
  }, [isDone])

  const { mutate: saveAnswer } = useMutation({
    mutationFn: async ({ termId, easeKey, reviewCount }: {
      termId: number
      easeKey: EaseKey
      reviewCount: number
    }) => {
      if (!user) return
      const sid = sessionIdRef.current
      await Promise.all([
        upsertTermProgress(user.id, termId, listId, easeKey, reviewCount),
        sid !== null ? logReview(sid, user.id, termId, EASE[easeKey]) : Promise.resolve(),
      ])
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['flashcard-progress', user?.id, listId] })
    },
  })

  const advance = useCallback(() => {
    if (currentIdx + 1 >= sessionTerms.length) {
      setIsDone(true)
    } else {
      setCurrentIdx(i => i + 1)
      setIsFlipped(false)
    }
    setFx(null)
  }, [currentIdx, sessionTerms.length])

  const handleAnswer = useCallback((key: EaseKey) => {
    const term = sessionTerms[currentIdx]
    if (!term || !user) return

    const currentProgress = progressMap[term.id]
    const reviewCount = currentProgress?.review_count ?? 0

    saveAnswer({ termId: term.id, easeKey: key, reviewCount })

    if (newTermIdsAtStartRef.current.has(term.id)) {
      answeredNewIdsRef.current.add(term.id)
    }

    setSessionStats(prev => ({
      known: prev.known + (key === 'known' ? 1 : 0),
      learning: prev.learning + (key === 'easy' || key === 'hard' ? 1 : 0),
      ignored: prev.ignored + (key === 'ignored' ? 1 : 0),
    }))

    // Visual feedback: known swipes right, hard/ignored swipes left
    if (key === 'known' || key === 'easy') {
      setFx('known')
    } else {
      setFx('review')
    }
    setTimeout(advance, 450)
  }, [currentIdx, sessionTerms, user, saveAnswer, progressMap, advance])

  // Keyboard shortcuts
  useEffect(() => {
    function onKey(e: KeyboardEvent) {
      if (isDone || !sessionTerms[currentIdx]) return
      if (e.key === ' ' || e.key === 'Enter') {
        e.preventDefault()
        setIsFlipped(v => !v)
        return
      }
      if (!isFlipped) return
      if (e.key.toLowerCase() === 'j') handleAnswer('known')
      else if (e.key.toLowerCase() === 'k') handleAnswer('hard')
      else if (e.key.toLowerCase() === 'i') handleAnswer('ignored')
    }
    window.addEventListener('keydown', onKey)
    return () => window.removeEventListener('keydown', onKey)
  }, [isDone, isFlipped, currentIdx, sessionTerms, handleAnswer])

  const total = sessionTerms.length
  const progressPct = total > 0 ? Math.round((currentIdx / total) * 100) : 0
  const current = sessionTerms[currentIdx]

  if (loadingTerms) {
    return (
      <div className="atelier flex items-center justify-center min-h-screen">
        <div className="w-8 h-8 border-2 border-[var(--at-line)] border-t-[var(--at-accent)] rounded-full animate-spin" />
      </div>
    )
  }

  if (sessionTerms.length === 0) {
    return (
      <div className="atelier flex flex-col items-center justify-center min-h-screen gap-4 px-4">
        <div className="at-serif text-5xl italic text-[var(--at-mute-2)]">All clear.</div>
        <p className="text-[var(--at-mute)] text-center max-w-sm">
          Không có thẻ nào cần học ngay bây giờ. Quay lại sau khi đến lịch ôn tập.
        </p>
        <button
          onClick={() => navigate({ to: '/flash-card/$listId', params: { listId: String(listId) } })}
          className="mt-4 px-6 py-2.5 bg-[var(--at-ink)] text-[var(--at-paper)] rounded-xl text-sm font-semibold hover:opacity-90 transition"
        >
          Quay lại danh sách
        </button>
      </div>
    )
  }

  if (isDone) {
    return (
      <div className="atelier flex flex-col items-center justify-center min-h-screen gap-8 px-4">
        <div className="text-center">
          <div className="at-serif italic text-[var(--at-accent)] text-6xl mb-4">Bravo.</div>
          <h2 className="at-serif text-3xl tracking-tight text-[var(--at-ink)] mb-2">Hoàn thành phiên học</h2>
          <p className="text-[var(--at-mute)]">Bạn đã ôn xong {total} thẻ trong phiên này</p>
        </div>
        <div className="flex gap-3">
          <div className="px-5 py-3 rounded-2xl border border-[var(--at-line)] bg-white text-center min-w-[88px]">
            <div className="at-serif text-3xl text-[var(--at-good)]">{sessionStats.known}</div>
            <div className="text-[10px] uppercase tracking-widest text-[var(--at-mute)] mt-1">Đã biết</div>
          </div>
          <div className="px-5 py-3 rounded-2xl border border-[var(--at-line)] bg-white text-center min-w-[88px]">
            <div className="at-serif text-3xl text-[var(--at-accent)]">{sessionStats.learning}</div>
            <div className="text-[10px] uppercase tracking-widest text-[var(--at-mute)] mt-1">Đang học</div>
          </div>
          <div className="px-5 py-3 rounded-2xl border border-[var(--at-line)] bg-white text-center min-w-[88px]">
            <div className="at-serif text-3xl text-[var(--at-mute-2)]">{sessionStats.ignored}</div>
            <div className="text-[10px] uppercase tracking-widest text-[var(--at-mute)] mt-1">Bỏ qua</div>
          </div>
        </div>
        <div className="flex gap-3">
          <button
            onClick={() => {
              setCurrentIdx(0)
              setIsFlipped(false)
              setIsDone(false)
              setSessionStats({ known: 0, learning: 0, ignored: 0 })
              sessionIdRef.current = null
              answeredNewIdsRef.current = new Set()
              newTermIdsAtStartRef.current = new Set()
              if (user) startSession(user.id, listId).then(s => { sessionIdRef.current = s.id })
            }}
            className="px-5 py-2.5 bg-[var(--at-ink)] text-[var(--at-paper)] rounded-xl text-sm font-semibold hover:opacity-90 transition"
          >
            Học lại
          </button>
          <button
            onClick={() => navigate({ to: '/flash-card/$listId', params: { listId: String(listId) } })}
            className="px-5 py-2.5 border border-[var(--at-line)] text-[var(--at-ink-2)] rounded-xl text-sm font-semibold bg-white hover:border-[var(--at-ink)] transition"
          >
            Xem danh sách
          </button>
        </div>
      </div>
    )
  }

  // Jump to a specific card in the deck (no progress write — just navigate)
  const jumpTo = (idx: number) => {
    setCurrentIdx(idx)
    setIsFlipped(false)
  }

  return (
    <div
      className="atelier fixed top-16 right-0 left-0 lg:left-60 bottom-20 lg:bottom-0 flex flex-col px-4 lg:px-6 py-3 overflow-hidden"
      style={{ background: 'var(--at-paper)' }}
    >
      {/* Header row: breadcrumb + serif title on left, actions on right */}
      <div className="flex items-end justify-between gap-4 mb-4 flex-shrink-0 min-w-0">
        <div className="min-w-0">
          <div className="flex items-center gap-2 mb-1 text-[13px]" style={{ color: 'var(--at-mute)' }}>
            <button
              onClick={() => navigate({ to: '/flash-card' })}
              className="hover:text-[var(--at-ink)] transition-colors"
            >
              Chủ đề
            </button>
            <span>/</span>
            <button
              onClick={() => navigate({ to: '/flash-card/$listId', params: { listId: String(listId) } })}
              className="hover:text-[var(--at-ink)] transition-colors truncate"
              style={{ color: 'var(--at-ink-2)' }}
            >
              {currentList?.title ?? 'Bộ thẻ'}
            </button>
          </div>
          <h1
            className="at-serif tracking-tight"
            style={{ fontSize: 40, fontWeight: 400, letterSpacing: '-0.025em', lineHeight: 1.05, color: 'var(--at-ink)' }}
          >
            Thẻ <i style={{ fontStyle: 'italic', color: 'var(--at-brand)' }}>{currentIdx + 1}</i>
            <span className="at-serif italic" style={{ color: 'var(--at-mute-2)' }}> / {total}</span>
          </h1>
        </div>
        <div className="flex gap-2 flex-shrink-0">
          <button
            onClick={() => navigate({ to: '/flash-card/$listId', params: { listId: String(listId) } })}
            className="inline-flex items-center gap-2 px-4 py-2.5 rounded-xl text-[13px] font-semibold transition-colors hover:bg-[var(--at-line-2)]"
            style={{ background: 'var(--at-surface)', border: '1px solid var(--at-line)', color: 'var(--at-ink-2)' }}
          >
            <span className="material-symbols-outlined" style={{ fontSize: 15 }}>arrow_back</span>
            Danh sách
          </button>
          <button
            onClick={() => current && toggleBookmark(current.id)}
            disabled={!current}
            className="inline-flex items-center gap-2 px-4 py-2.5 rounded-xl text-[13px] font-semibold transition-colors hover:bg-[var(--at-line-2)]"
            style={{
              background: current && bookmarks.has(current.id) ? 'var(--at-warm-soft)' : 'var(--at-surface)',
              border: '1px solid ' + (current && bookmarks.has(current.id) ? 'var(--at-warm)' : 'var(--at-line)'),
              color: current && bookmarks.has(current.id) ? 'var(--at-warm-ink)' : 'var(--at-ink-2)',
            }}
          >
            <span
              className="material-symbols-outlined"
              style={{
                fontSize: 15,
                fontVariationSettings: current && bookmarks.has(current.id) ? "'FILL' 1" : "'FILL' 0",
              }}
            >
              bookmark
            </span>
            Đánh dấu
          </button>
        </div>
      </div>

      {/* Body: card column + sidebar */}
      <div
        className="flex-1 min-h-0 lg:grid flex flex-col gap-5"
        style={{ gridTemplateColumns: 'minmax(0, 1fr) 260px' }}
      >
      {/* Main: card + actions + progress */}
      <div className="flex flex-col items-center justify-center min-h-0">
      {/* Card */}
      {current && (
        <div className="at-card-outer" style={{ maxWidth: 420, flexShrink: 0 }}>
          <div
            className={cn('at-card', isFlipped && 'is-flipped', fx === 'known' && 'fx-known', fx === 'review' && 'fx-review')}
            key={current.id}
            onClick={() => setIsFlipped(v => !v)}
            role="button"
            tabIndex={0}
            aria-label={isFlipped ? 'Lật để xem từ' : 'Lật để xem nghĩa'}
          >
            {/* FRONT */}
            <div className="at-card-face" style={{ padding: '20px 24px' }}>
              <div className="flex items-center justify-between">
                <span className="at-chip">
                  <span className="at-chip-dot" />
                  {current.part_of_speech?.toUpperCase() ?? 'TỪ VỰNG'}
                </span>
                <button
                  onClick={(e) => { e.stopPropagation(); speak(current.audio_tts_text ?? current.word) }}
                  className="w-9 h-9 rounded-lg grid place-items-center text-[var(--at-mute)] hover:bg-[var(--at-accent-soft)] hover:text-[var(--at-accent)] transition"
                  aria-label="Phát âm"
                >
                  <span className="material-symbols-outlined" style={{ fontSize: 20 }}>volume_up</span>
                </button>
              </div>

              <div className="flex-1 flex flex-col justify-center">
                <div className="at-word" style={{ fontSize: 'clamp(40px, 5vw, 60px)' }}>{current.word}</div>
                {(current.phonetic || current.part_of_speech) && (
                  <div className="at-mono text-sm text-[var(--at-mute)] mt-3">
                    {current.phonetic}
                    {current.part_of_speech && (
                      <span className="at-serif italic text-[var(--at-mute-2)]"> · {current.part_of_speech}</span>
                    )}
                  </div>
                )}
              </div>

              <div className="flex items-center justify-center gap-2 text-[11.5px] text-[var(--at-mute)]">
                <span className="at-kbd">Space</span>
                <span>để lật thẻ</span>
              </div>
            </div>

            {/* BACK */}
            <div className="at-card-face at-card-back" style={{ padding: '20px 24px' }}>
              <div className="flex items-center justify-between">
                <span className="at-chip at-chip-mute">
                  <span className="at-chip-dot" />
                  NGHĨA
                </span>
                <button
                  onClick={(e) => { e.stopPropagation(); speak(current.audio_tts_text ?? current.word) }}
                  className="w-9 h-9 rounded-lg grid place-items-center text-[var(--at-mute)] hover:bg-[var(--at-accent-soft)] hover:text-[var(--at-accent)] transition"
                  aria-label="Phát âm"
                >
                  <span className="material-symbols-outlined" style={{ fontSize: 20 }}>volume_up</span>
                </button>
              </div>

              <div className="flex-1 flex flex-col justify-center gap-4">
                <div className="at-meaning" style={{ fontSize: 22 }}>{current.definition ?? '—'}</div>
                {current.example && (
                  <div className="at-example">
                    <div className="at-serif italic text-[14px] leading-[1.45] text-[var(--at-ink-2)]">
                      "{current.example}"
                    </div>
                  </div>
                )}
              </div>

              <div className="flex items-center justify-center gap-2 text-[11.5px] text-[var(--at-mute)]">
                <span className="at-kbd">↵</span>
                <span>lật lại</span>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Actions */}
      <div className="mt-4 w-full" style={{ maxWidth: 420 }}>
        <div className={cn('flex items-stretch gap-2.5 w-full transition-opacity duration-300', !isFlipped && 'opacity-40 pointer-events-none')}>
          <button onClick={() => handleAnswer('ignored')} disabled={!isFlipped} className="at-action" style={{ padding: '11px 14px', fontSize: 13 }}>
            Bỏ qua <span className="at-kbd">I</span>
          </button>
          <button onClick={() => handleAnswer('hard')} disabled={!isFlipped} className="at-action at-action-review" style={{ padding: '11px 14px', fontSize: 13 }}>
            Cần ôn <span className="at-kbd">K</span>
          </button>
          <button onClick={() => handleAnswer('known')} disabled={!isFlipped} className="at-action at-action-known" style={{ padding: '11px 14px', fontSize: 13 }}>
            Đã thuộc
            <span className="at-kbd" style={{ background: 'rgba(255,255,255,0.16)', color: 'rgba(255,255,255,0.9)', border: 'none' }}>J</span>
          </button>
        </div>
      </div>

      {/* Progress */}
      <div className="mt-3 w-full" style={{ maxWidth: 420 }}>
        <div className="flex items-baseline justify-between mb-1.5 text-[12px] text-[var(--at-mute)]">
          <span>
            <b className="text-[var(--at-ink)] tabular-nums">{currentIdx + 1}</b> / {total} ·{' '}
            {sessionStats.known} biết · {sessionStats.learning} học · {sessionStats.ignored} bỏ
          </span>
          <span className="at-pct" style={{ fontSize: 18 }}>{progressPct}%</span>
        </div>
        <div className="at-progress-bar">
          <span style={{ width: `${progressPct}%` }} />
        </div>
      </div>
      </div>

      {/* Right sidebar */}
      <aside className="hidden lg:flex flex-col gap-3 min-h-0">
        {/* Today stats */}
        <div
          className="rounded-2xl p-4 flex-shrink-0"
          style={{ background: 'var(--at-surface)', border: '1px solid var(--at-line)' }}
        >
          <div className="at-eyebrow mb-2" style={{ fontSize: 11 }}>Hôm nay</div>
          <div className="grid grid-cols-2 gap-3 mt-1">
            <div>
              <div style={{ fontSize: 10, color: 'var(--at-mute)', textTransform: 'uppercase', fontWeight: 600, letterSpacing: '0.12em' }}>
                Đã học
              </div>
              <div
                className="at-serif"
                style={{ fontSize: 26, fontWeight: 400, letterSpacing: '-0.02em', lineHeight: 1.1, color: 'var(--at-ink)' }}
              >
                {sessionStats.known + sessionStats.learning + sessionStats.ignored}
              </div>
            </div>
            <div>
              <div style={{ fontSize: 10, color: 'var(--at-mute)', textTransform: 'uppercase', fontWeight: 600, letterSpacing: '0.12em' }}>
                Đúng
              </div>
              <div
                className="at-serif"
                style={{ fontSize: 26, fontWeight: 400, letterSpacing: '-0.02em', lineHeight: 1.1, color: 'var(--at-good)' }}
              >
                {sessionStats.known}
              </div>
            </div>
          </div>
        </div>

        {/* Cards in deck — compact rows (word only) */}
        <div
          className="rounded-2xl p-3 flex flex-col"
          style={{
            background: 'var(--at-surface)',
            border: '1px solid var(--at-line)',
            maxHeight: 'calc((100vh - 4rem) / 2)',
          }}
        >
          <div className="at-eyebrow mb-2 px-1" style={{ fontSize: 11 }}>Trong bộ này</div>
          <div className="flex-1 min-h-0 overflow-y-auto -mx-1 px-1">
            {sessionTerms.map((t, i) => {
              const p = progressMap[t.id]
              const isActive = i === currentIdx
              const isKnown = p?.status === 'known'
              const isBookmarked = bookmarks.has(t.id)
              return (
                <button
                  key={t.id}
                  onClick={() => jumpTo(i)}
                  className="w-full flex items-center gap-2.5 px-3 py-2.5 rounded-lg text-left transition-colors"
                  style={{
                    background: isActive ? 'var(--at-brand-soft)' : 'transparent',
                    borderTop: i === 0 || isActive ? 'none' : '1px solid var(--at-line)',
                  }}
                >
                  <span
                    className="at-serif italic flex-shrink-0 text-center"
                    style={{ fontSize: 13, color: 'var(--at-mute)', width: 20 }}
                  >
                    {i + 1}
                  </span>
                  <div className="flex-1 min-w-0">
                    <div
                      className="text-[13px] font-bold truncate"
                      style={{ color: isActive ? 'var(--at-brand-ink)' : 'var(--at-ink)' }}
                    >
                      {t.word}
                    </div>
                    <div
                      className="text-[11.5px] truncate mt-0.5"
                      style={{ color: 'var(--at-mute)' }}
                    >
                      {t.definition ?? '—'}
                    </div>
                  </div>
                  {isBookmarked && (
                    <span
                      className="material-symbols-outlined flex-shrink-0"
                      style={{ fontSize: 13, color: 'var(--at-warm)', fontVariationSettings: "'FILL' 1" }}
                    >
                      bookmark
                    </span>
                  )}
                  {isKnown && (
                    <span className="material-symbols-outlined flex-shrink-0" style={{ fontSize: 14, color: 'var(--at-good)' }}>
                      check
                    </span>
                  )}
                </button>
              )
            })}
          </div>
        </div>
      </aside>
      </div>
    </div>
  )
}
