'use client'

import { useState, useEffect, useCallback, useRef } from 'react'
import { LessonSession, LessonPhase, TimerState, PhaseDurations } from '@/lib/companion/types'
import {
  PHASE_ORDER,
  PHASE_DISPLAY_NAMES,
  PHASE_COLORS,
  DEFAULT_PHASE_DURATIONS,
  SYSTEM_TEMPLATES,
  getTimerColorStatus,
  STORAGE_KEYS,
} from '@/lib/companion/constants'

interface UseLessonSessionOptions {
  onPhaseComplete?: (phaseIndex: number) => void
  onLessonComplete?: (session: LessonSession) => void
  onOvertimeStart?: () => void
}

interface UseLessonSessionReturn {
  session: LessonSession | null
  timerState: TimerState | null
  startLesson: (data: {
    classId: string
    className?: string
    subject: string
    topic?: string
    templateId?: string
  }) => void
  endLesson: () => void
  pauseLesson: () => void
  resumeLesson: () => void
  extendTime: (minutes: number) => void
  skipPhase: () => void
  saveReflection: (rating: number, notes: string, nextSteps: string) => void
  addHomework: (title: string, dueDate: string) => void
  removeHomework: (id: string) => void
  isRunning: boolean
  isPaused: boolean
}

function createInitialPhases(durations: PhaseDurations): LessonPhase[] {
  return PHASE_ORDER.map((phaseId) => ({
    phase: phaseId,
    duration: durations[phaseId],
    status: 'planned',
    actualTime: 0,
  }))
}

function generateSessionId(): string {
  return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
}

export function useLessonSession(
  options: UseLessonSessionOptions = {}
): UseLessonSessionReturn {
  const { onPhaseComplete, onLessonComplete, onOvertimeStart } = options

  const [session, setSession] = useState<LessonSession | null>(null)
  const [timerState, setTimerState] = useState<TimerState | null>(null)

  const timerRef = useRef<NodeJS.Timeout | null>(null)
  const lastTickRef = useRef<number>(Date.now())
  const hasTriggeredOvertimeRef = useRef(false)

  // Calculate timer state from session
  const calculateTimerState = useCallback((sess: LessonSession): TimerState | null => {
    if (!sess || sess.status === 'completed') return null

    const currentPhase = sess.phases[sess.currentPhaseIndex]
    if (!currentPhase) return null

    const phaseDurationSeconds = currentPhase.duration * 60
    const elapsedInPhase = currentPhase.actualTime
    const remainingSeconds = phaseDurationSeconds - elapsedInPhase
    const progress = Math.min(elapsedInPhase / phaseDurationSeconds, 1)
    const isOvertime = remainingSeconds < 0

    return {
      isRunning: sess.status === 'in_progress' && !sess.isPaused,
      isPaused: sess.isPaused,
      elapsedSeconds: elapsedInPhase,
      remainingSeconds: Math.max(remainingSeconds, -999),
      totalSeconds: phaseDurationSeconds,
      progress,
      colorStatus: getTimerColorStatus(remainingSeconds, isOvertime),
      currentPhase,
    }
  }, [])

  // Timer tick function
  const tick = useCallback(() => {
    if (!session || session.isPaused || session.status !== 'in_progress') return

    const now = Date.now()
    const delta = Math.floor((now - lastTickRef.current) / 1000)
    lastTickRef.current = now

    if (delta <= 0) return

    setSession((prev) => {
      if (!prev) return null

      const updatedPhases = [...prev.phases]
      const currentPhase = updatedPhases[prev.currentPhaseIndex]
      if (!currentPhase) return prev

      currentPhase.actualTime += delta

      // Check for overtime
      const phaseDurationSeconds = currentPhase.duration * 60
      if (
        currentPhase.actualTime > phaseDurationSeconds &&
        !hasTriggeredOvertimeRef.current
      ) {
        hasTriggeredOvertimeRef.current = true
        onOvertimeStart?.()
      }

      // Update total elapsed time
      const totalElapsed = prev.elapsedTime + delta

      return {
        ...prev,
        phases: updatedPhases,
        elapsedTime: totalElapsed,
        overtimeMinutes: Math.max(
          0,
          Math.floor((currentPhase.actualTime - phaseDurationSeconds) / 60)
        ),
      }
    })
  }, [session, onOvertimeStart])

  // Start/stop timer based on session state
  useEffect(() => {
    if (session?.status === 'in_progress' && !session.isPaused) {
      lastTickRef.current = Date.now()
      timerRef.current = setInterval(tick, 100) // Update every 100ms for smooth animation
    } else {
      if (timerRef.current) {
        clearInterval(timerRef.current)
        timerRef.current = null
      }
    }

    return () => {
      if (timerRef.current) {
        clearInterval(timerRef.current)
      }
    }
  }, [session?.status, session?.isPaused, tick])

  // Update timer state when session changes
  useEffect(() => {
    if (session) {
      setTimerState(calculateTimerState(session))
    } else {
      setTimerState(null)
    }
  }, [session, calculateTimerState])

  // Persist session to localStorage
  useEffect(() => {
    if (session) {
      localStorage.setItem(STORAGE_KEYS.CURRENT_SESSION, JSON.stringify(session))
    }
  }, [session])

  // Restore session from localStorage on mount
  useEffect(() => {
    const stored = localStorage.getItem(STORAGE_KEYS.CURRENT_SESSION)
    if (stored) {
      try {
        const parsed = JSON.parse(stored) as LessonSession
        // Only restore if session is not completed and not too old (< 24h)
        const sessionTime = new Date(parsed.startTime).getTime()
        const isRecent = Date.now() - sessionTime < 24 * 60 * 60 * 1000

        if (parsed.status !== 'completed' && isRecent) {
          // Pause the restored session
          setSession({ ...parsed, isPaused: true })
        }
      } catch {
        // Invalid stored session, ignore
      }
    }
  }, [])

  const startLesson = useCallback(
    (data: {
      classId: string
      className?: string
      subject: string
      topic?: string
      templateId?: string
    }) => {
      // Find template durations
      let durations = DEFAULT_PHASE_DURATIONS
      if (data.templateId) {
        const template = SYSTEM_TEMPLATES.find((t) => t.templateId === data.templateId)
        if (template) {
          durations = template.durations as PhaseDurations
        }
      }

      const phases = createInitialPhases(durations)
      phases[0].status = 'active'
      phases[0].startedAt = new Date().toISOString()

      const newSession: LessonSession = {
        sessionId: generateSessionId(),
        classId: data.classId,
        className: data.className || data.classId,
        subject: data.subject,
        topic: data.topic,
        startTime: new Date().toISOString(),
        phases,
        totalPlannedDuration: Object.values(durations).reduce((a, b) => a + b, 0),
        currentPhaseIndex: 0,
        elapsedTime: 0,
        isPaused: false,
        pauseDuration: 0,
        overtimeMinutes: 0,
        status: 'in_progress',
        homeworkList: [],
        materials: [],
      }

      hasTriggeredOvertimeRef.current = false
      setSession(newSession)
    },
    []
  )

  const endLesson = useCallback(() => {
    if (!session) return

    const completedSession: LessonSession = {
      ...session,
      status: 'completed',
      endTime: new Date().toISOString(),
      phases: session.phases.map((p, i) => ({
        ...p,
        status: i <= session.currentPhaseIndex ? 'completed' : 'skipped',
        completedAt: i <= session.currentPhaseIndex ? new Date().toISOString() : undefined,
      })),
    }

    setSession(completedSession)
    onLessonComplete?.(completedSession)
  }, [session, onLessonComplete])

  const pauseLesson = useCallback(() => {
    if (!session || session.isPaused) return

    setSession((prev) =>
      prev
        ? {
            ...prev,
            isPaused: true,
            pausedAt: new Date().toISOString(),
            status: 'paused',
          }
        : null
    )
  }, [session])

  const resumeLesson = useCallback(() => {
    if (!session || !session.isPaused) return

    const pausedAt = session.pausedAt ? new Date(session.pausedAt).getTime() : Date.now()
    const pauseDelta = Math.floor((Date.now() - pausedAt) / 1000)

    setSession((prev) =>
      prev
        ? {
            ...prev,
            isPaused: false,
            pausedAt: undefined,
            pauseDuration: prev.pauseDuration + pauseDelta,
            status: 'in_progress',
          }
        : null
    )

    lastTickRef.current = Date.now()
  }, [session])

  const extendTime = useCallback(
    (minutes: number) => {
      if (!session) return

      setSession((prev) => {
        if (!prev) return null

        const updatedPhases = [...prev.phases]
        const currentPhase = updatedPhases[prev.currentPhaseIndex]
        if (!currentPhase) return prev

        currentPhase.duration += minutes

        // Reset overtime trigger if we've added time
        if (hasTriggeredOvertimeRef.current) {
          const phaseDurationSeconds = currentPhase.duration * 60
          if (currentPhase.actualTime < phaseDurationSeconds) {
            hasTriggeredOvertimeRef.current = false
          }
        }

        return {
          ...prev,
          phases: updatedPhases,
          totalPlannedDuration: prev.totalPlannedDuration + minutes,
        }
      })
    },
    [session]
  )

  const skipPhase = useCallback(() => {
    if (!session) return

    const nextPhaseIndex = session.currentPhaseIndex + 1

    // Check if this was the last phase
    if (nextPhaseIndex >= session.phases.length) {
      endLesson()
      return
    }

    setSession((prev) => {
      if (!prev) return null

      const updatedPhases = [...prev.phases]

      // Complete current phase
      updatedPhases[prev.currentPhaseIndex] = {
        ...updatedPhases[prev.currentPhaseIndex],
        status: 'completed',
        completedAt: new Date().toISOString(),
      }

      // Start next phase
      updatedPhases[nextPhaseIndex] = {
        ...updatedPhases[nextPhaseIndex],
        status: 'active',
        startedAt: new Date().toISOString(),
      }

      return {
        ...prev,
        phases: updatedPhases,
        currentPhaseIndex: nextPhaseIndex,
        overtimeMinutes: 0,
      }
    })

    hasTriggeredOvertimeRef.current = false
    onPhaseComplete?.(session.currentPhaseIndex)
  }, [session, endLesson, onPhaseComplete])

  const saveReflection = useCallback(
    (rating: number, notes: string, nextSteps: string) => {
      if (!session) return

      setSession((prev) =>
        prev
          ? {
              ...prev,
              reflection: {
                rating,
                notes,
                nextSteps,
                savedAt: new Date().toISOString(),
              },
            }
          : null
      )
    },
    [session]
  )

  const addHomework = useCallback(
    (title: string, dueDate: string) => {
      if (!session) return

      const newHomework = {
        id: `hw-${Date.now()}`,
        title,
        dueDate,
        completed: false,
      }

      setSession((prev) =>
        prev
          ? {
              ...prev,
              homeworkList: [...prev.homeworkList, newHomework],
            }
          : null
      )
    },
    [session]
  )

  const removeHomework = useCallback(
    (id: string) => {
      if (!session) return

      setSession((prev) =>
        prev
          ? {
              ...prev,
              homeworkList: prev.homeworkList.filter((hw) => hw.id !== id),
            }
          : null
      )
    },
    [session]
  )

  // Clear session (for starting new)
  const clearSession = useCallback(() => {
    setSession(null)
    localStorage.removeItem(STORAGE_KEYS.CURRENT_SESSION)
  }, [])

  return {
    session,
    timerState,
    startLesson,
    endLesson: session?.status === 'completed' ? clearSession : endLesson,
    pauseLesson,
    resumeLesson,
    extendTime,
    skipPhase,
    saveReflection,
    addHomework,
    removeHomework,
    isRunning: session?.status === 'in_progress' && !session?.isPaused,
    isPaused: session?.isPaused ?? false,
  }
}
