'use client'

import { useCallback, useEffect, useMemo, useState } from 'react'
import { motion, AnimatePresence } from 'motion/react'
import {
  GraduationCap,
  Layers,
  ArrowLeft,
  ChevronLeft,
  ChevronRight,
  Calendar,
  Plus,
  BarChart3,
  Loader2,
  BookOpen,
} from 'lucide-react'
import { useSearchParams } from 'next/navigation'
import { useLanguage } from '@/lib/i18n'
import { cn } from '@/lib/utils'
import { NoteChart } from '@/components/note-chart'
import { RevisionHeatmap } from './revision-heatmap'
import { toast } from 'sonner'

interface DeckSummary {
  id: string
  name: string
  notebookId: string | null
  totalCards: number
  dueCount: number
  masteredCount: number
  lastReviewedAt: string | null
}

interface FlashcardItem {
  id: string
  front: string
  back: string
  type: string
  due: boolean
  mastered: boolean
}

interface StatsResponse {
  heatmap: { date: string; count: number }[]
  retentionRate: number
  retentionByWeek: { week: string; rate: number }[]
  difficultCards: { id: string; front: string; easinessFactor: number; deckName: string }[]
}

type PageTab = 'decks' | 'progress'
type SessionGrade = 1 | 2 | 3 | 4

export function RevisionView() {
  const { t } = useLanguage()
  const searchParams = useSearchParams()
  const initialDeckId = searchParams.get('deckId')

  const [tab, setTab] = useState<PageTab>('decks')
  const [decks, setDecks] = useState<DeckSummary[]>([])
  const [loadingDecks, setLoadingDecks] = useState(true)
  const [stats, setStats] = useState<StatsResponse | null>(null)
  const [loadingStats, setLoadingStats] = useState(false)

  const [activeDeckId, setActiveDeckId] = useState<string | null>(null)
  const [deckCards, setDeckCards] = useState<FlashcardItem[]>([])
  const [deckStats, setDeckStats] = useState({ total: 0, due: 0, mastered: 0 })
  const [loadingDeck, setLoadingDeck] = useState(false)

  const [isSessionActive, setIsSessionActive] = useState(false)
  const [isSessionFinished, setIsSessionFinished] = useState(false)
  const [sessionCards, setSessionCards] = useState<FlashcardItem[]>([])
  const [currentIndex, setCurrentIndex] = useState(0)
  const [isFlipped, setIsFlipped] = useState(false)
  const [sessionGrades, setSessionGrades] = useState<Record<string, SessionGrade>>({})
  const [reviewing, setReviewing] = useState(false)

  const [newDeckName, setNewDeckName] = useState('')
  const [creatingDeck, setCreatingDeck] = useState(false)

  const loadDecks = useCallback(async () => {
    setLoadingDecks(true)
    try {
      const res = await fetch('/api/flashcards/decks')
      const data = await res.json()
      if (res.ok) setDecks(data.decks || [])
    } finally {
      setLoadingDecks(false)
    }
  }, [])

  const loadStats = useCallback(async () => {
    setLoadingStats(true)
    try {
      const res = await fetch('/api/flashcards/stats')
      const data = await res.json()
      if (res.ok) setStats(data)
    } finally {
      setLoadingStats(false)
    }
  }, [])

  const loadDeck = useCallback(async (deckId: string) => {
    setLoadingDeck(true)
    try {
      const res = await fetch(`/api/flashcards/decks/${deckId}`)
      const data = await res.json()
      if (!res.ok) {
        toast.error(data.error || t('flashcards.loadDeckFailed'))
        return
      }
      setActiveDeckId(deckId)
      setDeckCards(data.deck.cards || [])
      setDeckStats(data.stats)
    } finally {
      setLoadingDeck(false)
    }
  }, [t])

  useEffect(() => {
    loadDecks()
  }, [loadDecks])

  useEffect(() => {
    if (tab === 'progress') loadStats()
  }, [tab, loadStats])

  useEffect(() => {
    if (initialDeckId && !activeDeckId) {
      loadDeck(initialDeckId)
    }
  }, [initialDeckId, activeDeckId, loadDeck])

  const activeDeck = useMemo(
    () => decks.find((d) => d.id === activeDeckId),
    [decks, activeDeckId],
  )

  const sessionChartData = useMemo(() => {
    const counts = { 1: 0, 2: 0, 3: 0, 4: 0 }
    Object.values(sessionGrades).forEach((g) => { counts[g] += 1 })
    return [
      { label: t('flashcards.grade.hard'), value: counts[1] },
      { label: t('flashcards.grade.difficult'), value: counts[2] },
      { label: t('flashcards.grade.good'), value: counts[3] },
      { label: t('flashcards.grade.easy'), value: counts[4] },
    ]
  }, [sessionGrades, t])

  const startSession = useCallback((deckId: string, cardsInput?: FlashcardItem[], dueOnly = true) => {
    const cards = cardsInput ?? (activeDeckId === deckId ? deckCards : [])
    if (cards.length === 0) {
      void loadDeck(deckId)
      return
    }
    let toReview = dueOnly ? cards.filter((c) => c.due) : cards
    if (toReview.length === 0) toReview = cards
    const shuffled = [...toReview].sort(() => Math.random() - 0.5)
    setSessionCards(shuffled)
    setCurrentIndex(0)
    setIsFlipped(false)
    setSessionGrades({})
    setIsSessionActive(true)
    setIsSessionFinished(false)
    setActiveDeckId(deckId)
  }, [activeDeckId, deckCards, loadDeck])

  useEffect(() => {
    if (!initialDeckId) return
    let cancelled = false
    ;(async () => {
      const res = await fetch(`/api/flashcards/decks/${initialDeckId}`)
      const data = await res.json()
      if (cancelled || !res.ok) return
      const cards: FlashcardItem[] = data.deck?.cards || []
      setActiveDeckId(initialDeckId)
      setDeckCards(cards)
      setDeckStats(data.stats || { total: 0, due: 0, mastered: 0 })
      startSession(initialDeckId, cards)
    })()
    return () => { cancelled = true }
  }, [initialDeckId, startSession])

  const handleEvaluate = async (grade: SessionGrade) => {
    const card = sessionCards[currentIndex]
    if (!card || reviewing) return

    setReviewing(true)
    setSessionGrades((prev) => ({ ...prev, [card.id]: grade }))

    try {
      await fetch(`/api/flashcards/${card.id}/review`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ grade }),
      })
    } catch {
      toast.error(t('flashcards.reviewFailed'))
    } finally {
      setReviewing(false)
    }

    if (currentIndex < sessionCards.length - 1) {
      setTimeout(() => {
        setCurrentIndex((i) => i + 1)
        setIsFlipped(false)
      }, 250)
    } else {
      setTimeout(() => setIsSessionFinished(true), 250)
    }
  }

  useEffect(() => {
    if (!isSessionActive || isSessionFinished) return
    const onKey = (e: KeyboardEvent) => {
      if (e.code === 'Space') {
        e.preventDefault()
        setIsFlipped((f) => !f)
      } else if (isFlipped) {
        if (e.key === '1') handleEvaluate(1)
        if (e.key === '2') handleEvaluate(2)
        if (e.key === '3') handleEvaluate(3)
        if (e.key === '4') handleEvaluate(4)
      }
    }
    window.addEventListener('keydown', onKey)
    return () => window.removeEventListener('keydown', onKey)
  }, [isSessionActive, isSessionFinished, isFlipped, currentIndex, reviewing])

  const exitSession = () => {
    setIsSessionActive(false)
    setIsSessionFinished(false)
    if (activeDeckId) {
      loadDeck(activeDeckId)
      loadDecks()
    }
  }

  const createDeck = async () => {
    const name = newDeckName.trim()
    if (!name) return
    setCreatingDeck(true)
    try {
      const res = await fetch('/api/flashcards/decks', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name }),
      })
      const data = await res.json()
      if (res.ok) {
        setNewDeckName('')
        await loadDecks()
        toast.success(t('flashcards.deckCreated'))
        if (data.deck?.id) setActiveDeckId(data.deck.id)
      }
    } finally {
      setCreatingDeck(false)
    }
  }

  const formatDue = (dueCount: number) => {
    if (dueCount > 0) return t('flashcards.dueCount', { count: dueCount })
    return t('flashcards.upToDate')
  }

  return (
    <div className="h-full flex flex-col bg-memento-paper dark:bg-background overflow-y-auto">
      <div className="px-6 sm:px-10 py-5 flex items-center justify-between sticky top-0 bg-memento-paper/95 dark:bg-background/95 backdrop-blur-sm z-40 border-b border-border/40">
        <div className="flex items-center gap-3">
          {isSessionActive ? (
            <button
              type="button"
              onClick={exitSession}
              className="flex items-center gap-2 text-concrete hover:text-foreground transition-colors"
            >
              <ArrowLeft size={16} />
              <span className="text-xs font-bold uppercase tracking-widest">{t('flashcards.exitSession')}</span>
            </button>
          ) : (
            <div className="flex items-center gap-2">
              <GraduationCap className="text-brand-accent" size={20} />
              <h1 className="text-sm font-black tracking-widest uppercase">{t('nav.revision')}</h1>
            </div>
          )}
        </div>

        {!isSessionActive && (
          <div className="flex gap-1 p-1 rounded-lg bg-black/[0.04] dark:bg-white/[0.04]">
            {(['decks', 'progress'] as const).map((id) => (
              <button
                key={id}
                type="button"
                onClick={() => setTab(id)}
                className={cn(
                  'px-3 py-1.5 rounded-md text-[10px] font-bold uppercase tracking-wider transition-colors',
                  tab === id ? 'bg-white dark:bg-card shadow-sm text-brand-accent' : 'text-concrete',
                )}
              >
                {id === 'decks' ? t('flashcards.tabDecks') : t('flashcards.tabProgress')}
              </button>
            ))}
          </div>
        )}
      </div>

      <div className="flex-1 max-w-5xl mx-auto w-full p-6 sm:p-10">
        <AnimatePresence mode="wait">
          {isSessionActive && !isSessionFinished && sessionCards[currentIndex] && (
            <motion.div
              key="session"
              initial={{ opacity: 0, scale: 0.98 }}
              animate={{ opacity: 1, scale: 1 }}
              exit={{ opacity: 0 }}
              className="max-w-2xl mx-auto flex flex-col items-center gap-8"
            >
              <div className="w-full flex items-center justify-between text-xs text-concrete">
                <button
                  type="button"
                  disabled={currentIndex === 0}
                  onClick={() => { setCurrentIndex((i) => i - 1); setIsFlipped(false) }}
                  className="flex items-center gap-1 disabled:opacity-30"
                >
                  <ChevronLeft size={16} /> {t('flashcards.previous')}
                </button>
                <span className="font-mono font-bold px-3 py-1 rounded-full bg-black/[0.04] dark:bg-white/[0.06]">
                  {currentIndex + 1} / {sessionCards.length}
                </span>
                <button
                  type="button"
                  disabled={currentIndex >= sessionCards.length - 1}
                  onClick={() => { setCurrentIndex((i) => i + 1); setIsFlipped(false) }}
                  className="flex items-center gap-1 disabled:opacity-30"
                >
                  {t('flashcards.next')} <ChevronRight size={16} />
                </button>
              </div>

              <button
                type="button"
                onClick={() => setIsFlipped((f) => !f)}
                className="w-full max-w-md min-h-[240px] [perspective:1000px] cursor-pointer select-none"
              >
                <div
                  className={cn(
                    'relative w-full min-h-[240px] transition-transform duration-500 [transform-style:preserve-3d]',
                    isFlipped && '[transform:rotateY(180deg)]',
                  )}
                >
                  <div className="absolute inset-0 [backface-visibility:hidden] rounded-2xl border border-border bg-card p-8 flex flex-col shadow-sm">
                    <span className="text-[10px] uppercase tracking-widest text-concrete mb-4">{t('flashcards.front')}</span>
                    <p className="flex-1 flex items-center justify-center text-center text-lg font-serif font-semibold">
                      {sessionCards[currentIndex].front}
                    </p>
                    <span className="text-[10px] text-concrete/60 text-center">{t('flashcards.tapToFlip')}</span>
                  </div>
                  <div className="absolute inset-0 [backface-visibility:hidden] [transform:rotateY(180deg)] rounded-2xl border border-brand-accent/30 bg-brand-accent/5 p-8 flex flex-col shadow-md">
                    <span className="text-[10px] uppercase tracking-widest text-brand-accent mb-4">{t('flashcards.back')}</span>
                    <p className="flex-1 flex items-center justify-center text-center text-sm leading-relaxed overflow-y-auto">
                      {sessionCards[currentIndex].back}
                    </p>
                  </div>
                </div>
              </button>

              {isFlipped && (
                <div className="grid grid-cols-2 sm:grid-cols-4 gap-2 w-full max-w-md">
                  {([
                    [1, t('flashcards.grade.hard'), 'bg-red-500/10 text-red-600 border-red-500/20'],
                    [2, t('flashcards.grade.difficult'), 'bg-amber-500/10 text-amber-700 border-amber-500/20'],
                    [3, t('flashcards.grade.good'), 'bg-emerald-500/10 text-emerald-700 border-emerald-500/20'],
                    [4, t('flashcards.grade.easy'), 'bg-brand-accent/10 text-brand-accent border-brand-accent/30'],
                  ] as const).map(([grade, label, cls]) => (
                    <button
                      key={grade}
                      type="button"
                      disabled={reviewing}
                      onClick={() => handleEvaluate(grade as SessionGrade)}
                      className={cn('py-2.5 px-2 rounded-xl border text-[10px] font-bold uppercase tracking-wide', cls)}
                    >
                      {label}
                    </button>
                  ))}
                </div>
              )}
            </motion.div>
          )}

          {isSessionFinished && (
            <motion.div
              key="finished"
              initial={{ opacity: 0, y: 10 }}
              animate={{ opacity: 1, y: 0 }}
              className="max-w-lg mx-auto text-center space-y-6"
            >
              <GraduationCap size={40} className="mx-auto text-brand-accent" />
              <h2 className="text-2xl font-serif font-bold">{t('flashcards.sessionComplete')}</h2>
              <div className="h-48">
                <NoteChart type="bar" data={sessionChartData} height={180} />
              </div>
              <button
                type="button"
                onClick={exitSession}
                className="px-6 py-2.5 rounded-xl bg-brand-accent text-white text-xs font-bold uppercase tracking-wider"
              >
                {t('flashcards.backToDecks')}
              </button>
            </motion.div>
          )}

          {!isSessionActive && tab === 'decks' && (
            <motion.div key="decks" initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="space-y-8">
              {activeDeckId && deckCards.length > 0 && (
                <div className="p-5 rounded-2xl border border-brand-accent/25 bg-brand-accent/5 space-y-3">
                  <h3 className="font-serif font-semibold text-lg">{activeDeck?.name || t('flashcards.activeDeck')}</h3>
                  <div className="flex flex-wrap gap-3 text-xs text-concrete">
                    <span>{t('flashcards.statTotal', { count: deckStats.total })}</span>
                    <span>{t('flashcards.statDue', { count: deckStats.due })}</span>
                    <span>{t('flashcards.statMastered', { count: deckStats.mastered })}</span>
                  </div>
                  <button
                    type="button"
                    onClick={() => startSession(activeDeckId)}
                    disabled={loadingDeck}
                    className="px-4 py-2 rounded-lg bg-brand-accent text-white text-xs font-bold uppercase tracking-wider flex items-center gap-2"
                  >
                    {loadingDeck ? <Loader2 size={14} className="animate-spin" /> : <GraduationCap size={14} />}
                    {t('flashcards.startReview')}
                  </button>
                </div>
              )}

              <div className="flex flex-wrap gap-2 items-center">
                <input
                  value={newDeckName}
                  onChange={(e) => setNewDeckName(e.target.value)}
                  placeholder={t('flashcards.newDeckPlaceholder')}
                  className="flex-1 min-w-[180px] px-3 py-2 rounded-lg border border-border text-sm bg-transparent"
                />
                <button
                  type="button"
                  onClick={createDeck}
                  disabled={creatingDeck || !newDeckName.trim()}
                  className="px-3 py-2 rounded-lg border border-border text-xs font-bold flex items-center gap-1 disabled:opacity-50"
                >
                  {creatingDeck ? <Loader2 size={14} className="animate-spin" /> : <Plus size={14} />}
                  {t('flashcards.createDeck')}
                </button>
              </div>

              {loadingDecks ? (
                <div className="flex justify-center py-16"><Loader2 className="animate-spin text-concrete" /></div>
              ) : decks.length === 0 ? (
                <div className="text-center py-16 border border-dashed border-border rounded-2xl space-y-3">
                  <GraduationCap size={32} className="mx-auto text-concrete/40" />
                  <p className="text-sm text-concrete">{t('flashcards.emptyDecks')}</p>
                  <p className="text-xs text-concrete/60 max-w-md mx-auto">{t('flashcards.emptyDecksHint')}</p>
                </div>
              ) : (
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                  {decks.map((deck) => (
                    <div
                      key={deck.id}
                      className="p-5 rounded-2xl border border-border/60 bg-card/50 hover:border-brand-accent/30 transition-colors flex flex-col gap-4"
                    >
                      <div>
                        <h3 className="font-serif font-semibold truncate">{deck.name}</h3>
                        <p className="text-xs text-concrete flex items-center gap-1 mt-1">
                          <Layers size={12} />
                          {t('flashcards.cardCountLabel', { count: deck.totalCards })}
                        </p>
                      </div>
                      <div className="flex flex-wrap gap-2 text-[10px]">
                        {deck.dueCount > 0 ? (
                          <span className="px-2 py-1 rounded-full bg-red-500/10 text-red-600 font-bold border border-red-500/15">
                            {formatDue(deck.dueCount)}
                          </span>
                        ) : (
                          <span className="px-2 py-1 rounded-full bg-emerald-500/10 text-emerald-700 font-bold border border-emerald-500/15">
                            {t('flashcards.upToDate')}
                          </span>
                        )}
                        <span className="px-2 py-1 rounded-full border border-border flex items-center gap-1 font-mono">
                          <Calendar size={10} />
                          {deck.masteredCount}/{deck.totalCards} {t('flashcards.masteredShort')}
                        </span>
                      </div>
                      <div className="flex gap-2 pt-2 border-t border-border/40">
                        <button
                          type="button"
                          onClick={() => loadDeck(deck.id)}
                          className="flex-1 py-2 text-[10px] font-bold uppercase tracking-wider border border-border rounded-lg hover:bg-black/[0.03]"
                        >
                          {t('flashcards.viewDeck')}
                        </button>
                        <button
                          type="button"
                          onClick={async () => {
                            setLoadingDeck(true)
                            try {
                              const res = await fetch(`/api/flashcards/decks/${deck.id}`)
                              const data = await res.json()
                              if (res.ok) {
                                setActiveDeckId(deck.id)
                                setDeckCards(data.deck.cards || [])
                                setDeckStats(data.stats)
                                startSession(deck.id, data.deck.cards || [])
                              }
                            } finally {
                              setLoadingDeck(false)
                            }
                          }}
                          className="flex-1 py-2 text-[10px] font-bold uppercase tracking-wider bg-brand-accent text-white rounded-lg flex items-center justify-center gap-1"
                        >
                          <GraduationCap size={12} />
                          {t('flashcards.review')}
                        </button>
                      </div>
                    </div>
                  ))}
                </div>
              )}
            </motion.div>
          )}

          {!isSessionActive && tab === 'progress' && (
            <motion.div key="progress" initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="space-y-8">
              {loadingStats ? (
                <div className="flex justify-center py-16"><Loader2 className="animate-spin text-concrete" /></div>
              ) : stats ? (
                <>
                  <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
                    <div className="p-4 rounded-xl border border-border bg-card/50">
                      <p className="text-[10px] uppercase tracking-widest text-concrete">{t('flashcards.retentionRate')}</p>
                      <p className="text-3xl font-serif font-bold mt-1">{stats.retentionRate}%</p>
                    </div>
                    <div className="p-4 rounded-xl border border-border bg-card/50 sm:col-span-2">
                      <p className="text-[10px] uppercase tracking-widest text-concrete mb-2 flex items-center gap-1">
                        <BarChart3 size={12} /> {t('flashcards.retentionCurve')}
                      </p>
                      <NoteChart
                        type="line"
                        data={stats.retentionByWeek.map((w) => ({
                          label: w.week.slice(5),
                          value: w.rate,
                        }))}
                        height={120}
                      />
                    </div>
                  </div>

                  <RevisionHeatmap data={stats.heatmap} />

                  {stats.difficultCards.length > 0 && (
                    <div className="space-y-3">
                      <h3 className="text-sm font-bold uppercase tracking-widest text-concrete flex items-center gap-2">
                        <BookOpen size={14} /> {t('flashcards.difficultCards')}
                      </h3>
                      <ul className="space-y-2">
                        {stats.difficultCards.map((c) => (
                          <li key={c.id} className="p-3 rounded-xl border border-border/60 text-sm flex justify-between gap-4">
                            <span className="truncate">{c.front}</span>
                            <span className="text-[10px] font-mono text-concrete shrink-0">EF {c.easinessFactor.toFixed(2)}</span>
                          </li>
                        ))}
                      </ul>
                    </div>
                  )}
                </>
              ) : null}
            </motion.div>
          )}
        </AnimatePresence>
      </div>
    </div>
  )
}
