import { useState, useEffect, useRef, useCallback } from "react"
import { Pause, Play } from "lucide-react"
import { Button } from "@/app/_components/ui/button"
import { cn } from "@/app/_lib/utils"
import { Slider } from "@/app/_components/ui/slider"
import { getMonthName } from "@/app/_utils/common"

interface CrimeTimelapseProps {
    startYear: number
    endYear: number
    onChange?: (year: number, month: number, progress: number) => void
    onPlayingChange?: (isPlaying: boolean) => void
    className?: string
    autoPlay?: boolean
    autoPlaySpeed?: number // Time to progress through one month in ms
    enablePerformanceMode?: boolean // Flag untuk mode performa
}

export function CrimeTimelapse({
    startYear = 2020,
    endYear = 2024,
    onChange,
    onPlayingChange,
    className,
    autoPlay = true,
    autoPlaySpeed = 1000, // Speed of month progress
    enablePerformanceMode = true, // Default aktifkan mode performa tinggi
}: CrimeTimelapseProps) {
    const [currentYear, setCurrentYear] = useState<number>(startYear)
    const [currentMonth, setCurrentMonth] = useState<number>(1) // Start at January (1)
    const [progress, setProgress] = useState<number>(0) // Progress within the current month
    const [isPlaying, setIsPlaying] = useState<boolean>(autoPlay)
    const [isDragging, setIsDragging] = useState<boolean>(false)
    const animationRef = useRef<number | null>(null)
    const lastUpdateTimeRef = useRef<number>(0)
    const frameSkipCountRef = useRef<number>(0) // Untuk pelompatan frame

    // Jumlah frame yang akan dilewati saat performance mode aktif
    const frameSkipThreshold = enablePerformanceMode ? 3 : 0

    // Hitung total bulan dari awal hingga akhir tahun (memoisasi)
    const totalMonths = useRef(((endYear - startYear) * 12) + 12) // +12 untuk memasukkan semua bulan tahun akhir

    // Menggunakan useCallback untuk fungsi yang sering dipanggil
    const calculateOverallProgress = useCallback((): number => {
        const yearDiff = currentYear - startYear
        const monthProgress = (yearDiff * 12) + (currentMonth - 1)
        return ((monthProgress + progress) / (totalMonths.current - 1)) * 100
    }, [currentYear, currentMonth, progress, startYear, totalMonths])

    const calculateTimeFromProgress = useCallback((overallProgress: number): { year: number; month: number; progress: number } => {
        const totalProgress = (overallProgress * (totalMonths.current - 1)) / 100
        const monthsFromStart = Math.floor(totalProgress)

        const year = startYear + Math.floor(monthsFromStart / 12)
        const month = (monthsFromStart % 12) + 1 // 1-12 for months
        const monthProgress = totalProgress - Math.floor(totalProgress)

        return {
            year: Math.min(year, endYear),
            month: Math.min(month, 12),
            progress: monthProgress
        }
    }, [startYear, endYear, totalMonths])

    // Calculate the current position for the active marker
    const calculateMarkerPosition = useCallback((): string => {
        return `${calculateOverallProgress()}%`
    }, [calculateOverallProgress])

    // Optimasi animasi dengan throttling berbasis requestAnimationFrame
    const animate = useCallback((timestamp: number) => {
        if (!lastUpdateTimeRef.current) {
            lastUpdateTimeRef.current = timestamp
        }

        if (!isDragging) {
            // Performance optimization: skip frames in performance mode
            frameSkipCountRef.current++

            if (frameSkipCountRef.current > frameSkipThreshold || !enablePerformanceMode) {
                frameSkipCountRef.current = 0

                const elapsed = timestamp - lastUpdateTimeRef.current
                const progressIncrement = elapsed / autoPlaySpeed

                let newProgress = progress + progressIncrement
                let newMonth = currentMonth
                let newYear = currentYear

                if (newProgress >= 1) {
                    newProgress = 0
                    newMonth = currentMonth + 1

                    if (newMonth > 12) {
                        newMonth = 1
                        newYear = currentYear + 1

                        if (newYear > endYear) {
                            newYear = startYear
                            newMonth = 1
                        }
                    }

                    setCurrentMonth(newMonth)
                    setCurrentYear(newYear)
                }

                setProgress(newProgress)

                // Notify parent component only after calculating all changes
                if (onChange) {
                    onChange(newYear, newMonth, newProgress)
                }

                lastUpdateTimeRef.current = timestamp
            }
        }

        if (isPlaying) {
            animationRef.current = requestAnimationFrame(animate)
        }
    }, [isPlaying, isDragging, progress, currentMonth, currentYear, onChange,
        autoPlaySpeed, startYear, endYear, enablePerformanceMode, frameSkipThreshold])

    useEffect(() => {
        if (isPlaying) {
            lastUpdateTimeRef.current = 0
            frameSkipCountRef.current = 0
            animationRef.current = requestAnimationFrame(animate)
        } else if (animationRef.current) {
            cancelAnimationFrame(animationRef.current)
        }

        return () => {
            if (animationRef.current) {
                cancelAnimationFrame(animationRef.current)
            }
        }
    }, [isPlaying, animate])

    // Memoized handler for play/pause
    const handlePlayPause = useCallback(() => {
        setIsPlaying(prevState => {
            const newPlayingState = !prevState
            if (onPlayingChange) {
                onPlayingChange(newPlayingState)
            }
            return newPlayingState
        })
    }, [onPlayingChange])

    // Memoized handler for slider change
    const handleSliderChange = useCallback((value: number[]) => {
        const overallProgress = value[0]
        const { year, month, progress } = calculateTimeFromProgress(overallProgress)

        setCurrentYear(year)
        setCurrentMonth(month)
        setProgress(progress)

        if (onChange) {
            onChange(year, month, progress)
        }
    }, [calculateTimeFromProgress, onChange])

    const handleSliderDragStart = useCallback(() => {
        setIsDragging(true)
        if (onPlayingChange) {
            onPlayingChange(true) // Treat dragging as a form of "playing" for performance optimization
        }
    }, [onPlayingChange])

    const handleSliderDragEnd = useCallback(() => {
        setIsDragging(false)
        if (onPlayingChange) {
            onPlayingChange(isPlaying) // Restore to actual playing state
        }
    }, [isPlaying, onPlayingChange])

    // Komputasi tahun marker dilakukan sekali saja dan di-cache
    const yearMarkers = useRef<number[]>([])
    useEffect(() => {
        const markers = []
        for (let year = startYear; year <= endYear; year++) {
            markers.push(year)
        }
        yearMarkers.current = markers
    }, [startYear, endYear])

    // Gunakan React.memo untuk komponen child jika diperlukan
    // Contoh: const YearMarker = React.memo(({ year, isActive }) => { ... })

    return (
        <div className={cn("w-full bg-transparent text-emerald-500", className)}>
            <div className="relative">
                {/* Current month/year marker that moves with the slider */}
                <div
                    className={cn(
                        "absolute bottom-full mb-2 transform -translate-x-1/2 px-3 py-1 rounded-full text-xs font-bold z-20 transition-colors duration-300 bg-emerald-500 text-background",
                    )}
                    style={{ left: calculateMarkerPosition() }}
                >
                    {isPlaying}{getMonthName(currentMonth)} {currentYear}
                </div>

                {/* Wrap button and slider in their container */}
                <div className="px-2 flex gap-x-2">
                    {/* Play/Pause button */}
                    <Button
                        variant="ghost"
                        size="icon"
                        onClick={handlePlayPause}
                        className={cn(
                            "text-background rounded-full hover:text-background h-10 w-10 z-10 transition-colors duration-300 bg-emerald-500 hover:bg-emerald-500/50",
                        )}
                    >
                        {isPlaying ? <Pause className="h-5 w-5" /> : <Play className="h-5 w-5" />}
                    </Button>

                    {/* Slider */}
                    <Slider
                        value={[calculateOverallProgress()]}
                        min={0}
                        max={100}
                        step={0.01}
                        onValueChange={handleSliderChange}
                        onValueCommit={handleSliderDragEnd}
                        onPointerDown={handleSliderDragStart}
                        className="w-full [&>span:first-child]:h-1.5 [&>span:first-child]:bg-white/30 [&_[role=slider]]:bg-emerald-500 [&_[role=slider]]:w-3 [&_[role=slider]]:h-3 [&_[role=slider]]:border-0 [&>span:first-child_span]:bg-emerald-500 [&_[role=slider]:focus-visible]:ring-0 [&_[role=slider]:focus-visible]:ring-offset-0 [&_[role=slider]:focus-visible]:scale-105 [&_[role=slider]:focus-visible]:transition-transform"
                    />
                </div>

                {/* Year markers */}
                <div className="flex items-center relative h-10">
                    <div className="absolute inset-0 h-full flex">
                        {yearMarkers.current.map((year, index) => (
                            <div
                                key={year}
                                className={cn(
                                    "flex-1 h-full flex items-center justify-center relative",
                                    index < yearMarkers.current.length - 1 && ""
                                )}
                            >
                                <div
                                    className={cn(
                                        "text-sm transition-colors font-medium",
                                        year === currentYear ? "text-emerald-500 font-bold text-lg" : "text-white/50"
                                    )}
                                >
                                    {year}
                                </div>
                            </div>
                        ))}
                    </div>
                </div>
            </div>
        </div>
    )
}