import { useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useAuth } from '../context/AuthContext'
import CoachMessage from '../components/CoachMessage'
import UserMessage from '../components/UserMessage'
import QuickReplies from '../components/QuickReplies'

const API = '/api'

const initialData = {
  name: '',
  gender: '',
  age: '',
  height_cm: '',
  weight: '',
  neck_cm: '',
  waist_cm: '',
  hip_cm: '',
  experience_level: '',
  bench_1rm: '',
  squat_1rm: '',
  deadlift_1rm: '',
  goal: '',
  workouts_per_week: ''
}

const calcBodyFat = (gender, waist, neck, hip, height) => {
  if (!waist || !neck || !height) return null
  if (gender === 'female' && !hip) return null
  if (gender === 'male') {
    return Math.max(
      0,
      495 / (1.0324 - 0.19077 * Math.log10(waist - neck) + 0.15456 * Math.log10(height)) - 450
    ).toFixed(1)
  }
  return Math.max(
    0,
    495 / (1.29579 - 0.35004 * Math.log10(waist + hip - neck) + 0.221 * Math.log10(height)) - 450
  ).toFixed(1)
}

const toNumberOrNull = (value) => {
  if (value === '' || value === null || value === undefined) return null
  const numberValue = Number(value)
  return Number.isNaN(numberValue) ? null : numberValue
}

export default function ChatOnboarding() {
  const { token, updateProfile, refreshProfile } = useAuth()
  const navigate = useNavigate()
  const [data, setData] = useState(initialData)
  const [messages, setMessages] = useState([])
  const [currentIndex, setCurrentIndex] = useState(0)
  const [answers, setAnswers] = useState([])
  const [inputValue, setInputValue] = useState('')
  const [error, setError] = useState('')
  const [isTyping, setIsTyping] = useState(false)
  const [isSaving, setIsSaving] = useState(false)
  const endRef = useRef(null)
  const messageIdRef = useRef(0)
  const typingTimeoutRef = useRef(null)

  const questions = useMemo(() => {
    return [
      {
        id: 'name',
        field: 'name',
        type: 'text',
        prompt: 'Hej! Jag är din coach. Vad heter du?',
        placeholder: 'Ditt namn',
        inputType: 'text'
      },
      {
        id: 'goal',
        field: 'goal',
        type: 'options',
        prompt: values => `Kul att träffas${values.name ? ` ${values.name}` : ''}! Vad är ditt största mål?`,
        options: [
          { label: 'Bygga muskler', value: 'muscle' },
          { label: 'Styrka', value: 'strength' },
          { label: 'Gå ner i vikt', value: 'fat_loss' },
          { label: 'Hälsa', value: 'general' }
        ]
      },
      {
        id: 'experience_level',
        field: 'experience_level',
        type: 'options',
        prompt: 'Hur länge har du tränat?',
        options: [
          { label: 'Ny', value: 'beginner' },
          { label: '< 1 år', value: 'beginner' },
          { label: '1-3 år', value: 'intermediate' },
          { label: '3+ år', value: 'advanced' }
        ]
      },
      {
        id: 'workouts_per_week',
        field: 'workouts_per_week',
        type: 'options',
        prompt: 'Hur många pass kan du köra per vecka?',
        options: [2, 3, 4, 5, 6].map(n => ({ label: `${n}`, value: n }))
      },
      {
        id: 'gender',
        field: 'gender',
        type: 'options',
        prompt: 'Super! Vi tar några snabba basfrågor. Vilket kön identifierar du dig som?',
        options: [
          { label: 'Man', value: 'male' },
          { label: 'Kvinna', value: 'female' }
        ]
      },
      {
        id: 'age',
        field: 'age',
        type: 'text',
        prompt: 'Hur gammal är du?',
        placeholder: 'Ålder',
        inputType: 'number',
        validate: value => (value > 0 && value < 120 ? '' : 'Skriv in en giltig ålder.')
      },
      {
        id: 'height_cm',
        field: 'height_cm',
        type: 'text',
        prompt: 'Hur lång är du? (cm)',
        placeholder: '175',
        inputType: 'number',
        unit: 'cm',
        validate: value => (value > 50 && value < 260 ? '' : 'Skriv in din längd i cm.')
      },
      {
        id: 'weight',
        field: 'weight',
        type: 'text',
        prompt: 'Vad väger du just nu? (kg)',
        placeholder: '75',
        inputType: 'number',
        unit: 'kg',
        validate: value => (value > 20 && value < 300 ? '' : 'Skriv in din vikt i kg.')
      },
      {
        id: 'neck_cm',
        field: 'neck_cm',
        type: 'text',
        prompt: 'Om du vet: halsmått i cm?',
        placeholder: '38',
        inputType: 'number',
        unit: 'cm',
        optional: true
      },
      {
        id: 'waist_cm',
        field: 'waist_cm',
        type: 'text',
        prompt: 'Midjemått i cm?',
        placeholder: '85',
        inputType: 'number',
        unit: 'cm',
        optional: true
      },
      {
        id: 'hip_cm',
        field: 'hip_cm',
        type: 'text',
        prompt: 'Höftmått i cm?',
        placeholder: '95',
        inputType: 'number',
        unit: 'cm',
        optional: true,
        shouldAsk: values => values.gender === 'female'
      },
      {
        id: 'bench_1rm',
        field: 'bench_1rm',
        type: 'text',
        prompt: 'Har du en uppskattad 1RM i bänkpress? (valfritt, kg)',
        placeholder: '100',
        inputType: 'number',
        unit: 'kg',
        optional: true,
        shouldAsk: values => values.experience_level && values.experience_level !== 'beginner'
      },
      {
        id: 'squat_1rm',
        field: 'squat_1rm',
        type: 'text',
        prompt: '1RM i knäböj? (valfritt, kg)',
        placeholder: '140',
        inputType: 'number',
        unit: 'kg',
        optional: true,
        shouldAsk: values => values.experience_level && values.experience_level !== 'beginner'
      },
      {
        id: 'deadlift_1rm',
        field: 'deadlift_1rm',
        type: 'text',
        prompt: '1RM i marklyft? (valfritt, kg)',
        placeholder: '160',
        inputType: 'number',
        unit: 'kg',
        optional: true,
        shouldAsk: values => values.experience_level && values.experience_level !== 'beginner'
      }
    ]
  }, [])

  const currentQuestion = questions[currentIndex]

  const addMessage = (message) => {
    messageIdRef.current += 1
    setMessages(prev => [...prev, { id: messageIdRef.current, ...message }])
  }

  const scrollToBottom = () => {
    if (endRef.current) {
      endRef.current.scrollIntoView({ behavior: 'smooth', block: 'end' })
    }
  }

  useEffect(() => {
    scrollToBottom()
  }, [messages, isTyping])

  const getPrompt = (question, values) => {
    if (!question) return ''
    return typeof question.prompt === 'function' ? question.prompt(values) : question.prompt
  }

  useEffect(() => {
    if (messages.length === 0 && currentQuestion) {
      addMessage({ sender: 'coach', text: getPrompt(currentQuestion, data), questionIndex: currentIndex })
    }
    return () => {
      if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current)
    }
  }, [messages.length, currentQuestion, currentIndex, data])

  const applyAnswer = (values, question, value) => {
    if (!question.field) return values
    return { ...values, [question.field]: value }
  }

  const rebuildDataFromAnswers = (updatedAnswers) => {
    return updatedAnswers.reduce((acc, answer) => {
      const question = questions[answer.questionIndex]
      if (!question) return acc
      return applyAnswer(acc, question, answer.value)
    }, { ...initialData })
  }

  const findNextIndex = (startIndex, nextData) => {
    for (let i = startIndex + 1; i < questions.length; i += 1) {
      const question = questions[i]
      if (!question?.shouldAsk || question.shouldAsk(nextData)) return i
    }
    return null
  }

  const isMeasurementQuestion = (questionId) => ['weight', 'neck_cm', 'waist_cm', 'hip_cm'].includes(questionId)
  const isStrengthQuestion = (questionId) => ['bench_1rm', 'squat_1rm', 'deadlift_1rm'].includes(questionId)
  const isProfileQuestion = (questionId) => ['gender', 'age', 'height_cm', 'experience_level', 'goal', 'workouts_per_week'].includes(questionId)

  const saveProfile = async (values, complete = false) => {
    const payload = {
      gender: values.gender || null,
      age: toNumberOrNull(values.age),
      height_cm: toNumberOrNull(values.height_cm),
      experience_level: values.experience_level || null,
      goal: values.goal || null,
      workouts_per_week: toNumberOrNull(values.workouts_per_week),
      onboarding_complete: complete
    }
    await updateProfile(payload)
  }

  const saveMeasurements = async (values) => {
    const bodyFat = calcBodyFat(
      values.gender,
      toNumberOrNull(values.waist_cm),
      toNumberOrNull(values.neck_cm),
      toNumberOrNull(values.hip_cm),
      toNumberOrNull(values.height_cm)
    )

    if (!values.weight && !values.neck_cm && !values.waist_cm && !values.hip_cm) return

    await fetch(`${API}/user/measurements`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
      body: JSON.stringify({
        weight: toNumberOrNull(values.weight),
        neck_cm: toNumberOrNull(values.neck_cm),
        waist_cm: toNumberOrNull(values.waist_cm),
        hip_cm: toNumberOrNull(values.hip_cm),
        body_fat_pct: bodyFat
      })
    })
  }

  const saveStrength = async (values) => {
    if (!values.bench_1rm && !values.squat_1rm && !values.deadlift_1rm) return

    await fetch(`${API}/user/strength`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
      body: JSON.stringify({
        bench_1rm: toNumberOrNull(values.bench_1rm),
        squat_1rm: toNumberOrNull(values.squat_1rm),
        deadlift_1rm: toNumberOrNull(values.deadlift_1rm)
      })
    })
  }

  const maybeAutoSave = async (questionId, nextData, nextIndex) => {
    if (isProfileQuestion(questionId)) {
      await saveProfile(nextData, false)
    }

    if (isMeasurementQuestion(questionId)) {
      const nextQuestion = nextIndex !== null ? questions[nextIndex] : null
      if (!nextQuestion || !isMeasurementQuestion(nextQuestion.id)) {
        await saveMeasurements(nextData)
      }
    }

    if (isStrengthQuestion(questionId)) {
      const nextQuestion = nextIndex !== null ? questions[nextIndex] : null
      if (!nextQuestion || !isStrengthQuestion(nextQuestion.id)) {
        await saveStrength(nextData)
      }
    }
  }

  const handleAnswer = async (answerValue, answerLabel = null) => {
    if (!currentQuestion) return
    const label = answerLabel ?? `${answerValue}`

    setError('')

    const nextData = applyAnswer(data, currentQuestion, answerValue)
    const nextIndex = findNextIndex(currentIndex, nextData)

    addMessage({ sender: 'user', text: label, questionIndex: currentIndex })
    setAnswers(prev => [...prev, { questionIndex: currentIndex, value: answerValue, label }])
    setData(nextData)
    setInputValue('')

    try {
      await maybeAutoSave(currentQuestion.id, nextData, nextIndex)
    } catch (err) {
      console.error('Autosave error:', err)
    }

    if (nextIndex === null) {
      setIsTyping(true)
      typingTimeoutRef.current = setTimeout(async () => {
        addMessage({
          sender: 'coach',
          text: 'Perfekt! Jag har allt jag behöver. Låt mig bygga ditt program...',
          questionIndex: currentIndex + 1
        })
        setIsTyping(false)
        await finishOnboarding(nextData)
      }, 700)
      return
    }

    setIsTyping(true)
    typingTimeoutRef.current = setTimeout(() => {
      addMessage({ sender: 'coach', text: getPrompt(questions[nextIndex], nextData), questionIndex: nextIndex })
      setCurrentIndex(nextIndex)
      setIsTyping(false)
    }, 600)
  }

  const finishOnboarding = async (values) => {
    setIsSaving(true)
    try {
      await saveProfile(values, true)
      await saveMeasurements(values)
      await saveStrength(values)
      if (refreshProfile) await refreshProfile()
      navigate('/')
    } catch (err) {
      console.error('Onboarding error:', err)
      setIsSaving(false)
    }
  }

  const handleTextSubmit = () => {
    if (!currentQuestion) return
    const raw = inputValue.trim()
    if (!raw && !currentQuestion.optional) {
      setError('Skriv ett svar för att gå vidare.')
      return
    }

    let numericValue = raw
    if (currentQuestion.inputType === 'number' && raw) {
      const parsed = Number(raw)
      if (Number.isNaN(parsed)) {
        setError('Skriv ett giltigt nummer.')
        return
      }
      const validationMessage = currentQuestion.validate ? currentQuestion.validate(parsed) : ''
      if (validationMessage) {
        setError(validationMessage)
        return
      }
      numericValue = parsed
    }

    if (!raw && currentQuestion.optional) {
      handleAnswer('', 'Hoppar')
      return
    }

    const label = currentQuestion.unit ? `${raw} ${currentQuestion.unit}` : raw
    handleAnswer(numericValue, label)
  }

  const handleQuickReply = (option) => {
    if (option.action === 'back') {
      handleBack()
      return
    }
    if (option.action === 'skip') {
      handleAnswer('', 'Hoppar')
      return
    }
    handleAnswer(option.value, option.label)
  }

  const handleBack = () => {
    if (!answers.length) return
    const lastAnswer = answers[answers.length - 1]
    const targetIndex = lastAnswer.questionIndex
    const trimmedMessages = [...messages]
    const lastCoachIndex = trimmedMessages
      .map((msg, idx) => (msg.sender === 'coach' && msg.questionIndex === targetIndex ? idx : -1))
      .filter(idx => idx !== -1)
      .pop()

    if (lastCoachIndex !== undefined) {
      trimmedMessages.splice(lastCoachIndex + 1)
    }

    const updatedAnswers = answers.slice(0, -1)
    setAnswers(updatedAnswers)
    setMessages(trimmedMessages)
    setCurrentIndex(targetIndex)
    setData(rebuildDataFromAnswers(updatedAnswers))
    setIsTyping(false)
    setInputValue('')
    setError('')
  }

  const renderInputArea = () => {
    if (!currentQuestion) return null

    if (currentQuestion.type === 'options') {
      const options = [...currentQuestion.options]
      const actionOptions = []
      if (currentQuestion.optional) {
        actionOptions.push({ label: 'Hoppa över', action: 'skip', variant: 'ghost' })
      }
      if (answers.length) {
        actionOptions.push({ label: 'Ändra senaste', action: 'back', variant: 'ghost' })
      }

      return (
        <>
          <QuickReplies
            options={[...options, ...actionOptions]}
            onSelect={handleQuickReply}
            disabled={isTyping || isSaving}
          />
        </>
      )
    }

    const actionOptions = []
    if (currentQuestion.optional) {
      actionOptions.push({ label: 'Hoppa över', action: 'skip', variant: 'ghost' })
    }
    if (answers.length) {
      actionOptions.push({ label: 'Ändra senaste', action: 'back', variant: 'ghost' })
    }

    return (
      <div className="chat-input-area">
        <div className="chat-input-row">
          <input
            type={currentQuestion.inputType || 'text'}
            inputMode={currentQuestion.inputType === 'number' ? 'numeric' : 'text'}
            placeholder={currentQuestion.placeholder}
            value={inputValue}
            onChange={event => setInputValue(event.target.value)}
            onKeyDown={event => {
              if (event.key === 'Enter') handleTextSubmit()
            }}
            disabled={isTyping || isSaving}
          />
          <button
            type="button"
            className="send-btn"
            onClick={handleTextSubmit}
            disabled={isTyping || isSaving}
          >
            Skicka
          </button>
        </div>
        {error && <div className="chat-error">{error}</div>}
        <QuickReplies
          options={actionOptions}
          onSelect={handleQuickReply}
          disabled={isTyping || isSaving}
        />
      </div>
    )
  }

  return (
    <div className="chat-onboarding">
      <div className="chat-shell">
        <header className="chat-header">
          <div>
            <p className="chat-subtitle">Coach</p>
            <h1>Personlig onboarding</h1>
          </div>
          <span className={`chat-status ${isSaving ? 'saving' : ''}`}>
            {isSaving ? 'Sparar...' : 'Redo'}
          </span>
        </header>

        <div className="chat-messages">
          {messages.map(message => (
            message.sender === 'coach' ? (
              <CoachMessage key={message.id} text={message.text} />
            ) : (
              <UserMessage key={message.id} text={message.text} />
            )
          ))}
          {isTyping && <CoachMessage typing />}
          <div ref={endRef}></div>
        </div>

        <div className="chat-actions">
          {renderInputArea()}
        </div>
      </div>
    </div>
  )
}
