"use client"

import { Accordion } from "@/components/ui/accordion"
import { COOKIE_VALUES } from "@/data/general"
import { Player } from "@/lib/schema/player"
import { closestCenter, DndContext, DragEndEvent, KeyboardSensor, PointerSensor, useSensor, useSensors } from "@dnd-kit/core"
import { arrayMove, SortableContext, sortableKeyboardCoordinates, verticalListSortingStrategy } from "@dnd-kit/sortable"
import { useSortable } from "@dnd-kit/sortable"
import { CSS } from "@dnd-kit/utilities"
import Cookies from "js-cookie"
import { GripVertical } from "lucide-react"
import { usePathname } from "next/navigation"
import { useEffect, useRef, useState } from "react"

import ArcadeStats from "./_stats/arcade/arcade"
import BedwarsStats from "./_stats/bedwars/bedwars"
import BlitzStats from "./_stats/blitz/blitz"
import BuildBattleStats from "./_stats/build-battle/build-battle"
import ClassicStats from "./_stats/classic/classic"
import CopsAndCrimsStats from "./_stats/copsandcrims/copsandcrims"
import DuelsStats from "./_stats/duels/duels"
import MegaWallsStats from "./_stats/megawalls/megawalls"
import MurderMysteryStats from "./_stats/murder-mystery/murder-mystery"
import PitStats from "./_stats/pit/pit"
import SkyWarsStats from "./_stats/skywars/skywars"
import SmashHerosStats from "./_stats/smashheros/smashheros"
import SpeedUHCStats from "./_stats/speeduhc/speeduhc"
import TNTGamesStats from "./_stats/tnt-games/tnt-games"
import UHCStats from "./_stats/uhc/uhc"
import WarlordsStats from "./_stats/warlords/warlords"
import WoolGamesStats from "./_stats/woolgames/woolgames"

export function PlayerPageLoadText() {
    const path = usePathname()

    return <p>{`Loading stats for ${path.split("/").at(-1)}`}</p>
}

interface SortableStatItemProps {
    id: string
    children: React.ReactNode
}

function SortableStatItem({ id, children }: SortableStatItemProps) {
    const {
        attributes,
        listeners,
        setNodeRef,
        transform,
        transition,
        isDragging
    } = useSortable({ id })

    const style = {
        transform: CSS.Transform.toString(transform),
        transition,
        opacity: isDragging ? 0.5 : 1
    }

    return (
        <div ref={setNodeRef} style={style} className="relative group">
            <div
                {...attributes}
                {...listeners}
                className="absolute -left-6 top-1/2 z-10 p-1 opacity-0 transition-opacity -translate-y-1/2 group-hover:opacity-50 hover:opacity-100 cursor-grab active:cursor-grabbing"
            >
                <GripVertical className="size-4 text-muted-foreground" />
            </div>
            {children}
        </div>
    )
}

export function PlayerStats(
    { stats, achievements, layout }: {
        stats: NonNullable<Player["player"]["stats"]>
        achievements: Player["player"]["achievements"]
        layout: string[] | undefined
    }
) {
    const statsComponents = {
        "bedwars": <BedwarsStats stats={stats.Bedwars} />,
        "skywars": (
            <SkyWarsStats
                stats={stats.SkyWars}
                achievements_skywars_opal_obsession={achievements?.["skywars_opal_obsession"] ?? 0}
            />
        ),
        "duels": <DuelsStats stats={stats.Duels} />,
        "murder-mystery": <MurderMysteryStats stats={stats.MurderMystery} />,
        "build-battle": <BuildBattleStats stats={stats.BuildBattle} />,
        "uhc": <UHCStats stats={stats.UHC} />,
        "pit": <PitStats stats={stats.Pit} />,
        "tnt-games": <TNTGamesStats stats={stats.TNTGames} />,
        "megawalls": <MegaWallsStats stats={stats.MegaWalls} />,
        "copsandcrims": <CopsAndCrimsStats stats={stats.CopsAndCrims} />,
        "woolgames": <WoolGamesStats stats={stats.WoolGames} />,
        "blitz": <BlitzStats stats={stats.Blitz} />,
        "arcade": <ArcadeStats stats={stats.Arcade} />,
        "speeduhc": <SpeedUHCStats stats={stats.SpeedUHC} uhcCoins={stats.UHC?.coins} />,
        "smashheros": <SmashHerosStats stats={stats.SmashHeros} />,
        "warlords": <WarlordsStats stats={stats.Warlords} />,
        "classic": (
            <ClassicStats
                stats={{
                    arena: stats.ArenaBrawl,
                    paintball: stats.Paintball
                }}
            />
        )
    } as const

    const defaultOrder = Object.keys(statsComponents)
    const orderToUse = layout || defaultOrder

    const [statsOrder, setStatsOrder] = useState<string[]>(layout || defaultOrder)
    const [isClient, setIsClient] = useState(false)

    const sensors = useSensors(
        useSensor(PointerSensor),
        useSensor(KeyboardSensor, {
            coordinateGetter: sortableKeyboardCoordinates
        })
    )

    const cookieOpts = useRef<Parameters<typeof Cookies.set>[2]>({
        secure: process.env.NODE_ENV === "production",
        sameSite: "lax",
        expires: 365
    })

    function updateStatsOrder(arr: string[]) {
        Cookies.set(COOKIE_VALUES.statsOrder, JSON.stringify(arr), cookieOpts.current)
    }

    function handleDragEnd(event: DragEndEvent) {
        const { active, over } = event

        if (over && active.id !== over.id) {
            const oldIndex = statsOrder.indexOf(active.id as string)
            const newIndex = statsOrder.indexOf(over.id as string)
            const newOrder = arrayMove(statsOrder, oldIndex, newIndex)

            setStatsOrder(newOrder)
            updateStatsOrder(newOrder)
        }
    }

    useEffect(() => {
        setIsClient(true)
        if (layout && layout.length > 0) {
            setStatsOrder(layout)
        }
        const cookie = Cookies.get(COOKIE_VALUES.statsOrder)
        if (cookie) {
            Cookies.set(COOKIE_VALUES.statsOrder, cookie, cookieOpts.current)
        }
    }, [layout, cookieOpts])

    if (!isClient) {
        return (
            <div className="mx-auto w-full lg:mx-0 lg:w-3/4 max-w-120 md:max-w-7/10">
                <Accordion type="multiple" className="space-y-4">
                    {orderToUse.map((statKey) => (
                        <div key={statKey}>
                            {statsComponents[statKey as keyof typeof statsComponents]}
                        </div>
                    ))}
                </Accordion>
            </div>
        )
    }

    return (
        <div className="mx-auto w-full lg:mx-0 lg:w-3/4 max-w-120 md:max-w-7/10">
            <DndContext
                sensors={sensors}
                collisionDetection={closestCenter}
                onDragEnd={handleDragEnd}
            >
                <SortableContext items={statsOrder} strategy={verticalListSortingStrategy}>
                    <Accordion type="multiple" className="space-y-4">
                        {statsOrder.map((statKey) => (
                            <SortableStatItem key={statKey} id={statKey}>
                                {statsComponents[statKey as keyof typeof statsComponents]}
                            </SortableStatItem>
                        ))}
                    </Accordion>
                </SortableContext>
            </DndContext>
        </div>
    )
}
