import React from 'react'
import { getUser, getColorTestFor, setColorTestFor } from '../utils/storage'
import ColorTestConsent from './ColorTestConsent'
import ColorTestIshihara from './ColorTestIshihara'
import ColorTestResult from './ColorTestResult'
import { colorTestApi } from '../api/colorTest'
import { useColorBlindness } from '../context/ColorBlindnessContext'
import CustomModal from './CustomModal'

export default function ColorTestManager() {
  const { updateFromTest } = useColorBlindness()
  const [user, setUser] = React.useState(getUser())

  React.useEffect(() => {
    const onUserChange = () => {
      const u = getUser()
      setUser(u)
      if (u?.id) {
        setState(getColorTestFor(u.id))
      } else {
        setState({ status: 'not_started' })
      }
    }
    window.addEventListener('kk_user_changed', onUserChange)
    return () => window.removeEventListener('kk_user_changed', onUserChange)
  }, [])

  const userId = user?.id ?? null
  const [state, setState] = React.useState(() => (userId ? getColorTestFor(userId) : { status: 'not_started' }))
  const [phase, setPhase] = React.useState('idle') // idle | consent | ishihara | result
  const [answers, setAnswers] = React.useState(null)
  const [result, setResult] = React.useState(null)
  const [plates, setPlates] = React.useState([]) // {id,url,expected}

  React.useEffect(() => {
    if (!userId) return
    const st = getColorTestFor(userId)
    setState(st)

    // Auto-trigger test for new users or those who haven't started
    if (st.status === 'not_started' && !st.dontShow) {
      setPhase('consent')
    }
  }, [userId])

  // Listen for global re-test trigger from Profile page
  React.useEffect(() => {
    if (!userId) return
    const onRetest = async () => {
      // Reset state and open consent
      const next = { status: 'not_started', dontShow: false }
      setColorTestFor(userId, next)
      setState(next)
      setPhase('consent')
      try { await colorTestApi.event({ user_id: userId || 0, event_type: 'retest_requested', payload: {} }) } catch { }
    }
    window.addEventListener('kk_color_test_retest', onRetest)
    return () => window.removeEventListener('kk_color_test_retest', onRetest)
  }, [userId])

  const persist = (patch) => { if (!userId) return; const next = { ...getColorTestFor(userId), ...patch }; setColorTestFor(userId, next); setState(next) }

  const handleStart = ({ dontShow }) => {
    persist({ status: 'in_progress', dontShow: !!dontShow })
    setPhase('ishihara')
      ; (async () => {
        try {
          const ctrl = new AbortController();
          const timer = setTimeout(() => ctrl.abort(), 2000)
          const list = await colorTestApi.ishiharaList()
          clearTimeout(timer)
          let all = (list?.data || []).map(it => ({ url: encodeURI(it.url), expected: String(it.expected ?? '').trim(), cat: it.cat || null }))
          // Shuffle all, then pick 6
          for (let i = all.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [all[i], all[j]] = [all[j], all[i]]
          }
          const maxCount = Math.min(20, all.length)
          // Always try to use all available if less than 20 to ensure balance
          const count = maxCount
          const pick = all.slice(0, count).map((it, idx) => ({ id: idx + 1, ...it }))
          if (pick.length) setPlates(pick)
        } catch { }
      })()
  }
  const [modal, setModal] = React.useState({ open: false, title: '', msg: '', type: 'confirm', onConfirm: null })

  const showConfirm = (msg, onConfirm) => {
    setModal({
      open: true,
      title: 'Konfirmasi',
      msg,
      type: 'confirm',
      onConfirm: () => {
        setModal(m => ({ ...m, open: false }))
        onConfirm()
      }
    })
  }

  const handleSkip = ({ dontShow }) => {
    showConfirm('Apakah Anda yakin ingin melewati tes ini?', () => {
      persist({ status: 'skipped', dontShow: !!dontShow })
      setPhase('idle')
    })
  }
  const onIshiharaDone = async (ans) => {
    setAnswers(ans)
    // Compare answers vs expected and score per category axis
    const total = ans.length || 0
    let correct = 0
    const axes = { protan: { total: 0, wrong: 0 }, deutan: { total: 0, wrong: 0 }, tritan: { total: 0, wrong: 0 } }
    if (plates && plates.length) {
      ans.forEach((a, i) => {
        const exp = String(plates[i]?.expected || '').trim()
        const seen = (a?.value || '').trim()
        const ok = exp && seen && seen !== '?' && seen.replace(/\s+/g, '') === exp
        if (ok) correct++
        const cat = plates[i]?.cat
        if (cat && axes[cat]) {
          axes[cat].total += 1
          if (!ok) axes[cat].wrong += 1
        }
      })
    }
    const rate = total ? (correct / total) : 0
    // Determine dominant axis of confusion
    const scores = Object.entries(axes).map(([k, v]) => ({ k, ratio: v.total ? (v.wrong / v.total) : 0, total: v.total }))
    scores.sort((a, b) => b.ratio - a.ratio)
    const top = scores[0]
    // Heuristic classification
    let classification = 'Normal'
    let severity = 'none'

    // Achromatopsia: Very low overall correct rate (< 20%)
    // This means they missed almost everything (Protan, Deutan, and Tritan plates)
    if (rate < 0.2) {
      classification = 'Monochromacy (Achromatopsia)'
      severity = 'severe'
    } else if (top && top.total >= 3 && top.ratio >= 0.4) {
      // We need at least 3 plates of a category to be confident
      // 0.4 ratio means missing ~2 out of 5 plates -> Mild/Anomaly

      const axisMap = {
        protan: ['Protanomaly', 'Protanopia'],
        deutan: ['Deuteranomaly', 'Deuteranopia'],
        tritan: ['Tritanomaly', 'Tritanopia']
      }

      let typeLabel = 'Normal'

      if (top.ratio >= 0.8) {
        // Severe: Opia
        typeLabel = axisMap[top.k][1]
        severity = 'severe'
      } else if (top.ratio >= 0.5) {
        // Moderate: Opia (leaning severe) or Strong Anomaly
        // Simplification: Treat high miss rate as Opia for better assistance, 
        // or keep as Anomaly if we want to be strict. 
        // Ishihara is hard to distinguish perfectly without an anomaloscope.
        // Let's call it Opia if > 60%, Anomaly if 0.4-0.6
        if (top.ratio >= 0.65) {
          typeLabel = axisMap[top.k][1] // Opia
          severity = 'moderate'
        } else {
          typeLabel = axisMap[top.k][0] // Anomaly
          severity = 'moderate'
        }
      } else {
        // Mild: Anomaly
        typeLabel = axisMap[top.k][0]
        severity = 'mild'
      }
      classification = typeLabel
    } else if (rate < 0.9) {
      // Missed a few random plates but no dominant axis
      classification = 'Borderline'
      severity = 'mild'
    }
    // Confidence blends overall correctness and dominant-axis strength
    const axisConf = top ? (0.5 * top.ratio) : 0
    const confidence = Math.max(0.5, Math.min(0.97, 0.5 * rate + axisConf))
    const short_note = (
      classification === 'Monochromacy (Achromatopsia)'
        ? 'Jawaban sangat rendah dan banyak tidak terlihat; indikasi kuat akromatopsia.'
        : (classification === 'Normal'
          ? 'Jawaban konsisten dengan persepsi warna normal pada screening.'
          : `Pola jawaban menunjukkan kecenderungan ${classification}.`)
    )
    const recommendation = (
      classification === 'Normal'
        ? 'Lanjutkan belajar seperti biasa. Kami tetap menjaga kontras tinggi untuk aksesibilitas.'
        : 'Kami sarankan materi dengan kontras lebih tinggi dan ikon pendukung.'
    )
    const res = { classification, severity, confidence, short_note, recommendation }

    persist({ status: 'completed', ishihara: { answers: ans }, result: res })

    try {
      if (user) {
        await colorTestApi.save({ user_id: userId || 0, ishihara_answers: ans, d15_order: [], classification, severity, confidence })
        await colorTestApi.event({ user_id: userId || 0, event_type: 'ishihara_done', payload: { count: ans?.length || 0 } })
        await colorTestApi.event({ user_id: userId || 0, event_type: 'completed', payload: res })

        // Auto-update global color blindness mode
        if (updateFromTest) updateFromTest(classification)
      }
    } catch { }

    setResult(res)
    setPhase('result')
  }
  const onIshiharaCancel = () => {
    showConfirm('Apakah Anda yakin ingin melewati tes ini?', () => {
      persist({ status: 'skipped' })
      setPhase('idle')
    })
  }
  // D15 removed

  const closeAll = () => { setPhase('idle') }

  if (!user) return null
  // Ensure we show the result if phase is 'result', even if dontShow is set
  if (phase !== 'result' && state.dontShow && (state.status === 'skipped' || state.status === 'completed')) return null

  return (
    <>
      <CustomModal
        isOpen={modal.open}
        title={modal.title}
        message={modal.msg}
        type={modal.type}
        onConfirm={modal.onConfirm}
        onCancel={() => setModal(m => ({ ...m, open: false }))}
      />
      {phase === 'consent' && (
        <ColorTestConsent userName={user.name} onStart={handleStart} onSkip={handleSkip} />
      )}
      {phase === 'ishihara' && (
        <ColorTestIshihara images={plates} onDone={onIshiharaDone} onCancel={onIshiharaCancel} />
      )}
      {phase === 'result' && (
        <ColorTestResult result={result} onClose={closeAll} onDetail={closeAll} />
      )}
    </>
  )
}
