import { useEffect, useRef, useState } from 'react'
import './Feed.css'
import { useAuth } from '../context/AuthContext'
import {
  getActiveLearningPair, getWords, getQuestions, getUserProgress,
  getLanguageOptions, langById,
  saveProgress, addPointsToPair,
} from '../api/directus'
import NewWordTextCard   from '../components/NewWordTextCard'
import NewWordVoiceCard  from '../components/NewWordVoiceCard'
import LetterOrderCard   from '../components/LetterOrderCard'
import SentenceFillCard  from '../components/SentenceFillCard'

// Ein Wort gilt als gemeistert, wenn es in der aktiven Sprachrichtung
// mindestens MASTERY_THRESHOLD korrekt beantwortete Kacheln gesammelt hat.
const MASTERY_THRESHOLD = 3
// Wie viele verschiedene Wörter gleichzeitig im Feed erscheinen
const FEED_WORD_BUDGET  = 6

// Punkteformel: selbes/niedrigeres Level = 1 Punkt, jeder Level höher = +1 Punkt
function computePoints(cardLevel, userLevel) {
  return Math.max(1, 1 + ((cardLevel || 1) - (userLevel || 1)))
}

function shuffle(arr) {
  const a = [...arr]
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1))
    ;[a[i], a[j]] = [a[j], a[i]]
  }
  return a
}

const pickN = (arr, n) => shuffle(arr).slice(0, Math.max(0, n))

function pickWordsToLearn(unmastered, userLevel, budget) {
  if (unmastered.length === 0) return []
  const same      = unmastered.filter(w => (w.level || 1) === userLevel)
  const higher    = unmastered.filter(w => (w.level || 1) >  userLevel && (w.level || 1) <= userLevel + 2)
  const farHigher = unmastered.filter(w => (w.level || 1) >  userLevel + 2)
  const lower     = unmastered.filter(w => (w.level || 1) <  userLevel)

  if (same.length > 0) {
    const sameN   = Math.ceil(budget * 0.8)
    const higherN = budget - sameN
    let result = [
      ...pickN(same,   Math.min(sameN,   same.length)),
      ...pickN(higher, Math.min(higherN, higher.length)),
    ]
    if (result.length < budget) {
      const used = new Set(result.map(w => w.id))
      const rest = unmastered.filter(w => !used.has(w.id))
      result = [...result, ...pickN(rest, budget - result.length)]
    }
    return shuffle(result)
  }
  if (higher.length    > 0) return pickN(higher,    budget)
  if (farHigher.length > 0) return pickN(farHigher, budget)
  return pickN(lower, budget)
}

function buildWordCards(words, userLevel, fromLang, toLang) {
  const cards = []
  words.forEach(w => {
    const word        = w[`title_${toLang.suffix}`]
    const translation = w[`title_${fromLang.suffix}`]
    if (!word || !translation) return
    const level  = w.level || 1
    const points = computePoints(level, userLevel)

    const base = { language: toLang.label, points, word, translation, level }

    cards.push({
      type: 'text',
      meta: { wordId: w.id, cardType: 'write', points, level },
      card: { ...base, baseForm: word, prompt: `Schreib das Wort auf ${toLang.label}` },
    })
    cards.push({
      type: 'voice',
      meta: { wordId: w.id, cardType: 'speak', points, level },
      card: { ...base, baseForm: word, prompt: `Sprich das Wort auf ${toLang.label}`, speechLang: toLang.speech },
    })
    if (word.length >= 4) {
      cards.push({
        type: 'letter',
        meta: { wordId: w.id, cardType: 'write', points, level },
        card: { ...base, prompt: 'Tippe die Buchstaben in der richtigen Reihenfolge' },
      })
    }
  })
  return cards
}

function buildQuestionCardsFor(questions, masteredWordIds, userLevel, toLang) {
  const cards = []
  questions.forEach(q => {
    const wordIds = (q.related_words || []).map(rw => rw.words_id).filter(Boolean)
    if (wordIds.length === 0) return
    if (!wordIds.every(id => masteredWordIds.has(id))) return

    const qText  = q[`question_${toLang.suffix}`]
    const answer = q[`answer_${toLang.suffix}`]
    if (!qText || !answer) return

    const level  = q.level || 1
    const points = computePoints(level, userLevel)

    cards.push({
      type: 'sentence',
      meta: { questionId: q.id, wordIds, cardType: 'sentence_fill', points, level },
      card: {
        language: toLang.label, points, level,
        word: answer,
        translation: qText,
        prompt: 'Antworte auf die Frage',
      },
    })
  })
  return cards
}

export default function Feed() {
  const { user, token } = useAuth()
  const [cards, setCards]                 = useState([])
  const [loading, setLoading]             = useState(true)
  const [ctx, setCtx]                     = useState(null)
  const [runningPoints, setRunningPoints] = useState(0)
  const [empty, setEmpty]                 = useState(false)

  // Laufende Mastery-Verwaltung für diese Session
  const correctsRef       = useRef({})   // wordId -> Anzahl korrekter Antworten (persistiert + session)
  const masteredRef       = useRef(new Set())
  const questionsRef      = useRef([])
  const appendedQRef      = useRef(new Set()) // bereits angehängte questionIds
  const userLevelRef      = useRef(1)
  const toLangRef         = useRef(null)
  const pointsQueueRef    = useRef(Promise.resolve()) // serialisiert Punkte-Updates

  useEffect(() => {
    async function load() {
      try {
        const [pair, langs] = await Promise.all([
          getActiveLearningPair(user.username, token),
          getLanguageOptions(),
        ])
        if (!pair) { setEmpty(true); setLoading(false); return }

        const fromLang = langById(pair.language_from, langs)
        const toLang   = langById(pair.language_to,   langs)
        if (!fromLang || !toLang) { setEmpty(true); setLoading(false); return }

        const userLevel = pair.current_level || 1

        const [words, questions, progress] = await Promise.all([
          getWords(token),
          getQuestions(token),
          getUserProgress(user.username, token, pair.language_to),
        ])

        const correctsByWord = {}
        progress.forEach(p => {
          if (p.result === 'correct' && p.word) {
            correctsByWord[p.word] = (correctsByWord[p.word] || 0) + 1
          }
        })
        const mastered = new Set(
          Object.entries(correctsByWord)
            .filter(([, c]) => c >= MASTERY_THRESHOLD)
            .map(([id]) => id)
        )

        correctsRef.current  = correctsByWord
        masteredRef.current  = mastered
        questionsRef.current = questions
        userLevelRef.current = userLevel
        toLangRef.current    = toLang

        const unmastered = words.filter(w => !mastered.has(w.id))
        const chosen     = pickWordsToLearn(unmastered, userLevel, FEED_WORD_BUDGET)

        const wordCards     = buildWordCards(chosen, userLevel, fromLang, toLang)
        const questionCards = buildQuestionCardsFor(questions, mastered, userLevel, toLang)

        // bereits angehängte Frage-IDs merken, damit wir sie nicht doppelt einstreuen
        questionCards.forEach(c => appendedQRef.current.add(c.meta.questionId))

        const allCards = [...wordCards, ...questionCards]
        setCards(allCards)
        setEmpty(allCards.length === 0)
        setCtx({
          pair,
          fromLangId: pair.language_from,
          toLangId:   pair.language_to,
          profileId:  user.username,
        })
        setRunningPoints(pair.points || 0)
      } catch (err) {
        console.error('Feed load error', err)
        setEmpty(true)
      } finally {
        setLoading(false)
      }
    }
    load()
  }, [user.username, token])

  async function handleComplete(item, result) {
    if (!ctx) return
    const earned = result === 'correct' ? (item.meta.points || 1) : 0

    saveProgress({
      user: ctx.profileId,
      word:     item.meta.wordId     || null,
      question: item.meta.questionId || null,
      card_type: item.meta.cardType,
      result,
      points_earned: earned,
      language_from: ctx.fromLangId,
      language_to:   ctx.toLangId,
    }, token).catch(() => {})

    // Punkte serialisiert patchen, damit parallele Karten nicht denselben Basiswert überschreiben
    if (earned > 0) {
      setRunningPoints(p => p + earned)
      pointsQueueRef.current = pointsQueueRef.current.then(async () => {
        ctx.pair.points = (ctx.pair.points || 0) + earned
        try { await addPointsToPair(ctx.pair.id, ctx.pair.points, token) } catch {}
      })
    }

    // In-Session-Mastery: korrekte Wort-Antwort erhöht Zähler; neu gemasterte
    // Wörter können Frage-Kacheln freischalten.
    if (result === 'correct' && item.meta.wordId) {
      const wid = item.meta.wordId
      const newCount = (correctsRef.current[wid] || 0) + 1
      correctsRef.current[wid] = newCount

      if (!masteredRef.current.has(wid) && newCount >= MASTERY_THRESHOLD) {
        masteredRef.current.add(wid)

        const newQuestions = questionsRef.current.filter(q => {
          if (appendedQRef.current.has(q.id)) return false
          const wordIds = (q.related_words || []).map(rw => rw.words_id).filter(Boolean)
          if (wordIds.length === 0) return false
          return wordIds.every(id => masteredRef.current.has(id))
        })

        if (newQuestions.length > 0) {
          const extra = buildQuestionCardsFor(
            newQuestions,
            masteredRef.current,
            userLevelRef.current,
            toLangRef.current,
          )
          extra.forEach(c => appendedQRef.current.add(c.meta.questionId))
          setCards(prev => [...prev, ...extra])
          setEmpty(false)
        }
      }
    }
  }

  if (loading) {
    return (
      <div className="feed">
        <div style={{ padding: '60px 24px', textAlign: 'center', color: '#9A8F85', fontFamily: 'DM Sans, sans-serif' }}>
          Lade Karten…
        </div>
      </div>
    )
  }

  if (empty) {
    return (
      <div className="feed">
        <div style={{ padding: '60px 24px', textAlign: 'center', color: '#9A8F85', fontFamily: 'DM Sans, sans-serif' }}>
          Super! Du hast alle Wörter deines Levels gemeistert. Neue Wörter kommen bald.
        </div>
      </div>
    )
  }

  return (
    <div className="feed">
      {cards.map((item, i) => {
        const enrichedCard = { ...item.card, totalPoints: runningPoints }
        const handler = (r) => handleComplete(item, r)
        return (
          <div key={i} className="feed-slot">
            {item.type === 'text'     && <NewWordTextCard  card={enrichedCard} onComplete={handler} />}
            {item.type === 'voice'    && <NewWordVoiceCard card={enrichedCard} onComplete={handler} />}
            {item.type === 'letter'   && <LetterOrderCard  card={enrichedCard} onComplete={handler} />}
            {item.type === 'sentence' && <SentenceFillCard card={enrichedCard} onComplete={handler} />}
          </div>
        )
      })}
    </div>
  )
}
