"use client"

import { getCrimeRateColor } from "@/app/_utils/map"
import { IExtrusionLayerProps } from "@/app/_utils/types/map"
import { useEffect, useRef } from "react"

export default function DistrictExtrusionLayer({
    visible = true,
    map,
    tilesetId,
    focusedDistrictId,
    crimeDataByDistrict,
}: IExtrusionLayerProps) {
    const animationRef = useRef<number | null>(null)
    const bearingRef = useRef(0)
    const rotationAnimationRef = useRef<number | null>(null)

    // Handle extrusion layer creation and updates
    useEffect(() => {
        if (!map || !visible) return

        const onStyleLoad = () => {
            if (!map) return

            try {
                const layers = map.getStyle().layers
                let firstSymbolId: string | undefined
                for (const layer of layers) {
                    if (layer.type === "symbol") {
                        firstSymbolId = layer.id
                        break
                    }
                }

                if (!map.getLayer("district-extrusion")) {
                    map.addLayer(
                        {
                            id: "district-extrusion",
                            type: "fill-extrusion",
                            source: "districts",
                            "source-layer": "Districts",
                            paint: {
                                "fill-extrusion-color": [
                                    "case",
                                    ["has", "kode_kec"],
                                    [
                                        "match",
                                        ["get", "kode_kec"],
                                        focusedDistrictId || "",
                                        getCrimeRateColor(crimeDataByDistrict[focusedDistrictId || ""]?.level),
                                        "transparent",
                                    ],
                                    "transparent",
                                ],
                                "fill-extrusion-height": [
                                    "case",
                                    ["has", "kode_kec"],
                                    ["match", ["get", "kode_kec"], focusedDistrictId || "", 500, 0],
                                    0,
                                ],
                                "fill-extrusion-base": 0,
                                "fill-extrusion-opacity": 0.8,
                            },
                            filter: ["==", ["get", "kode_kec"], focusedDistrictId || ""],
                        },
                        firstSymbolId,
                    )
                } else {
                    // Update existing layer
                    map.setFilter("district-extrusion", ["==", ["get", "kode_kec"], focusedDistrictId || ""])

                    map.setPaintProperty("district-extrusion", "fill-extrusion-color", [
                        "case",
                        ["has", "kode_kec"],
                        [
                            "match",
                            ["get", "kode_kec"],
                            focusedDistrictId || "",
                            getCrimeRateColor(crimeDataByDistrict[focusedDistrictId || ""]?.level),
                            "transparent",
                        ],
                        "transparent",
                    ])
                }
            } catch (error) {
                console.error("Error adding district extrusion layer:", error)
            }
        }

        if (map.isStyleLoaded()) {
            onStyleLoad()
        } else {
            map.once("style.load", onStyleLoad)
        }

        return () => {
            if (animationRef.current) {
                cancelAnimationFrame(animationRef.current)
                animationRef.current = null
            }
        }
    }, [map, visible, tilesetId, focusedDistrictId, crimeDataByDistrict])

    // Handle extrusion height animation
    useEffect(() => {
        if (!map || !map.getLayer("district-extrusion")) return

        try {
            if (focusedDistrictId) {
                const startHeight = 0
                const targetHeight = 800
                const duration = 700
                const startTime = performance.now()

                const animateHeight = (currentTime: number) => {
                    const elapsed = currentTime - startTime
                    const progress = Math.min(elapsed / duration, 1)
                    const easedProgress = progress * (2 - progress)
                    const currentHeight = startHeight + (targetHeight - startHeight) * easedProgress

                    map.setPaintProperty("district-extrusion", "fill-extrusion-height", [
                        "case",
                        ["has", "kode_kec"],
                        ["match", ["get", "kode_kec"], focusedDistrictId, currentHeight, 0],
                        0,
                    ])

                    if (progress < 1) {
                        animationRef.current = requestAnimationFrame(animateHeight)
                    } else {
                        // Start rotation after extrusion completes
                        startRotation()
                    }
                }

                if (animationRef.current) {
                    cancelAnimationFrame(animationRef.current)
                }
                animationRef.current = requestAnimationFrame(animateHeight)
            } else {
                const startHeight = 800
                const targetHeight = 0
                const duration = 500
                const startTime = performance.now()

                const animateHeightDown = (currentTime: number) => {
                    const elapsed = currentTime - startTime
                    const progress = Math.min(elapsed / duration, 1)
                    const easedProgress = progress * (2 - progress)
                    const currentHeight = startHeight + (targetHeight - startHeight) * easedProgress

                    map.setPaintProperty("district-extrusion", "fill-extrusion-height", [
                        "case",
                        ["has", "kode_kec"],
                        ["match", ["get", "kode_kec"], "", currentHeight, 0],
                        0,
                    ])

                    if (progress < 1) {
                        animationRef.current = requestAnimationFrame(animateHeightDown)
                    }
                }

                if (animationRef.current) {
                    cancelAnimationFrame(animationRef.current)
                }
                animationRef.current = requestAnimationFrame(animateHeightDown)

                // Stop rotation when unfocusing
                if (rotationAnimationRef.current) {
                    cancelAnimationFrame(rotationAnimationRef.current)
                    rotationAnimationRef.current = null
                }
                bearingRef.current = 0
            }
        } catch (error) {
            console.error("Error animating district extrusion:", error)
        }
    }, [map, focusedDistrictId])

    // Cleanup on unmount
    useEffect(() => {
        return () => {
            if (animationRef.current) {
                cancelAnimationFrame(animationRef.current)
                animationRef.current = null
            }
            if (rotationAnimationRef.current) {
                cancelAnimationFrame(rotationAnimationRef.current)
                rotationAnimationRef.current = null
            }
        }
    }, [])

    // Start rotation animation
    const startRotation = () => {
        if (!map || !focusedDistrictId) return

        const rotationSpeed = 0.05 // degrees per frame

        const animate = () => {
            if (!map || !focusedDistrictId) {
                if (rotationAnimationRef.current) {
                    cancelAnimationFrame(rotationAnimationRef.current)
                    rotationAnimationRef.current = null
                }
                return
            }

            // Update bearing with smooth increment
            bearingRef.current = (bearingRef.current + rotationSpeed) % 360
            map.setBearing(bearingRef.current)

            // Continue the animation
            rotationAnimationRef.current = requestAnimationFrame(animate)
        }

        // Start the animation loop
        if (rotationAnimationRef.current) {
            cancelAnimationFrame(rotationAnimationRef.current)
        }
        rotationAnimationRef.current = requestAnimationFrame(animate)
    }

    return null
}
