import { useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { api } from '@/lib/api'
import { hasWebsiteScope, scopedQueryKey } from '@/lib/queryKeys'
import { useAppStore } from '@/store/useAppStore'
import { SafeHtml } from '@/components/SafeHtml'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Skeleton } from '@/components/ui/skeleton'
import { CheckCircle2, Send } from 'lucide-react'

const ACTIVE_SESSION_KEY = 'irt-student-active-session'

type SessionResponse = {
  session_id: string
  wp_user_id: string
  website_id: number
  tryout_id: string
  start_time: string
  end_time: string | null
  expires_at: string | null
  is_completed: boolean
  total_benar: number
  NM: number | null
  NN: number | null
}

type NextItemResponse = {
  status: 'item' | 'completed'
  item_id?: number
  stem?: string
  options?: Record<string, string>
  slot?: number
  level?: string
  display_level?: string
  generated_by?: string
  source_snapshot_question_id?: number | null
  reason?: string
  items_answered?: number
}

function formatRemaining(seconds: number | null) {
  if (seconds === null) return '-'
  const clamped = Math.max(0, seconds)
  const minutes = Math.floor(clamped / 60)
  const rest = clamped % 60
  return `${minutes}:${String(rest).padStart(2, '0')}`
}

function getErrorMessage(error: unknown) {
  return error instanceof Error ? error.message : 'Request failed.'
}

export default function StudentSession() {
  const { sessionId } = useParams<{ sessionId: string }>()
  const { websiteId } = useAppStore()
  const queryClient = useQueryClient()
  const navigate = useNavigate()
  const [selectedResponse, setSelectedResponse] = useState('')
  const [now, setNow] = useState(0)
  const itemStartedAtRef = useRef(0)

  const sessionKey = scopedQueryKey(websiteId, 'student-session', sessionId)
  const nextItemKey = scopedQueryKey(websiteId, 'student-next-item', sessionId)

  const sessionQuery = useQuery({
    queryKey: sessionKey,
    queryFn: async () => {
      const res = await api.get<SessionResponse>(`/session/${sessionId}`)
      return res.data
    },
    enabled: hasWebsiteScope(websiteId) && Boolean(sessionId),
  })

  const nextItemQuery = useQuery({
    queryKey: nextItemKey,
    queryFn: async () => {
      const res = await api.get<NextItemResponse>(`/session/${sessionId}/next_item`)
      return res.data
    },
    enabled: hasWebsiteScope(websiteId) && Boolean(sessionId) && !sessionQuery.data?.is_completed,
  })

  const submitMutation = useMutation({
    mutationFn: async () => {
      if (!nextItemQuery.data?.item_id) throw new Error('No active item.')
      const startedAt = itemStartedAtRef.current || Date.now()
      const timeSpent = Math.max(0, Math.round((Date.now() - startedAt) / 1000))
      await api.post(`/session/${sessionId}/submit_answer`, {
        item_id: nextItemQuery.data.item_id,
        response: selectedResponse,
        time_spent: timeSpent,
      })
    },
    onSuccess: () => {
      setSelectedResponse('')
      itemStartedAtRef.current = Date.now()
      queryClient.invalidateQueries({ queryKey: nextItemKey })
      queryClient.invalidateQueries({ queryKey: sessionKey })
    },
  })

  const completeMutation = useMutation({
    mutationFn: async () => {
      const res = await api.post(`/session/${sessionId}/complete`, {
        end_time: new Date().toISOString(),
        user_answers: [],
      })
      return res.data
    },
    onSuccess: () => {
      localStorage.removeItem(ACTIVE_SESSION_KEY)
      queryClient.invalidateQueries({ queryKey: sessionKey })
      navigate(`/student/result/${sessionId}`)
    },
  })

  const expiresAt = sessionQuery.data?.expires_at
  useEffect(() => {
    if (!expiresAt) {
      return
    }
    const timer = window.setInterval(() => setNow(Date.now()), 1000)
    return () => window.clearInterval(timer)
  }, [expiresAt])

  useEffect(() => {
    if (sessionId && !sessionQuery.data?.is_completed) {
      localStorage.setItem(ACTIVE_SESSION_KEY, sessionId)
    }
  }, [sessionId, sessionQuery.data?.is_completed])

  useEffect(() => {
    if (nextItemQuery.data?.item_id) {
      itemStartedAtRef.current = Date.now()
    }
  }, [nextItemQuery.data?.item_id])

  const options = useMemo(() => Object.entries(nextItemQuery.data?.options || {}), [nextItemQuery.data?.options])
  const remainingSeconds = useMemo(() => {
    if (!expiresAt || !now) return null
    return Math.ceil((new Date(expiresAt).getTime() - now) / 1000)
  }, [expiresAt, now])

  if (!hasWebsiteScope(websiteId)) {
    return <div className="text-muted-foreground">Select a website to load the session.</div>
  }

  if (sessionQuery.isLoading || nextItemQuery.isLoading) {
    return <Skeleton className="h-[520px] w-full" />
  }

  if (sessionQuery.isError || !sessionQuery.data) {
    return (
      <Alert variant="destructive">
        <AlertTitle>Session failed to load</AlertTitle>
        <AlertDescription>Check the active website and session ID.</AlertDescription>
      </Alert>
    )
  }

  if (sessionQuery.data.is_completed) {
    return (
      <Card>
        <CardHeader>
          <CardTitle>Session Completed</CardTitle>
          <CardDescription>{sessionQuery.data.session_id}</CardDescription>
        </CardHeader>
        <CardContent>
          <Button onClick={() => navigate(`/student/result/${sessionId}`)}>View Result</Button>
        </CardContent>
      </Card>
    )
  }

  const nextItem = nextItemQuery.data

  return (
    <div className="space-y-6">
      <div className="flex flex-wrap items-start justify-between gap-4">
        <div>
          <h1 className="text-3xl font-bold tracking-tight">Tryout Session</h1>
          <p className="text-muted-foreground mt-1">
            {sessionQuery.data.tryout_id} · Student {sessionQuery.data.wp_user_id}
          </p>
        </div>
        <div className="flex gap-2">
          <Badge variant="secondary">Answered {nextItem?.items_answered ?? 0}</Badge>
          <Badge variant={remainingSeconds !== null && remainingSeconds < 300 ? 'destructive' : 'outline'}>
            {formatRemaining(remainingSeconds)}
          </Badge>
        </div>
      </div>

      {(submitMutation.isError || completeMutation.isError || nextItemQuery.isError) && (
        <Alert variant="destructive">
          <AlertTitle>Session action failed</AlertTitle>
          <AlertDescription>
            {getErrorMessage(submitMutation.error || completeMutation.error || nextItemQuery.error)}
          </AlertDescription>
        </Alert>
      )}

      {nextItem?.status === 'completed' ? (
        <Card>
          <CardHeader>
            <CardTitle>Ready to Complete</CardTitle>
            <CardDescription>{nextItem.reason || 'No more questions are available for this session.'}</CardDescription>
          </CardHeader>
          <CardContent>
            <Button onClick={() => completeMutation.mutate()} disabled={completeMutation.isPending}>
              <CheckCircle2 className="mr-2 h-4 w-4" />
              {completeMutation.isPending ? 'Completing...' : 'Complete Session'}
            </Button>
          </CardContent>
        </Card>
      ) : (
        <Card>
          <CardHeader>
            <CardTitle>Question {nextItem?.slot ?? '-'}</CardTitle>
            <CardDescription className="capitalize">{nextItem?.display_level || nextItem?.level || 'item'}</CardDescription>
          </CardHeader>
          <CardContent className="space-y-6">
            <div className="rounded-md border p-4">
              <SafeHtml html={nextItem?.stem || ''} />
            </div>
            <div className="grid gap-3 md:grid-cols-2">
              {options.map(([key, value]) => (
                <button
                  key={key}
                  type="button"
                  onClick={() => setSelectedResponse(key)}
                  className={`rounded-md border p-4 text-left transition-colors ${
                    selectedResponse === key ? 'border-primary bg-primary/5' : 'hover:bg-muted'
                  }`}
                >
                  <span className="font-mono font-semibold">{key}.</span>{' '}
                  <SafeHtml html={value} className="inline" />
                </button>
              ))}
            </div>
            <div className="flex justify-end">
              <Button
                onClick={() => submitMutation.mutate()}
                disabled={!selectedResponse || submitMutation.isPending}
              >
                <Send className="mr-2 h-4 w-4" />
                {submitMutation.isPending ? 'Submitting...' : 'Submit Answer'}
              </Button>
            </div>
          </CardContent>
        </Card>
      )}
    </div>
  )
}
