"use client"

import { PlayerIGN, PlayerRank } from "@/app/(stats)/_components/displayname"
import { Card, CardContent } from "@/components/ui/card"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { formatDate, formatNumber } from "@/lib/formatters"
import { head } from "@/lib/hypixel/general"
import { Guild } from "@/lib/schema/guild"
import { playerForGuildSchema } from "@/lib/schema/player"
import { ApiResponse } from "@/types"
import { useQueries } from "@tanstack/react-query"
import Image from "next/image"
import Link from "next/link"
import { useEffect, useRef } from "react"
import { toast } from "sonner"
import z from "zod"

type PlayerForGuild = z.infer<typeof playerForGuildSchema>
type MemberWithPlayer = Guild["guild"]["members"][number] & {
    player?: PlayerForGuild["player"]
    loading?: boolean
    error?: boolean
}

export function GuildMembers({ members, ranks }: { members: Guild["guild"]["members"], ranks: Guild["guild"]["ranks"] }) {
    const hasShownToast = useRef(false)
    const totalMembers = members.length
    const TOAST_ID = "guild.members.progress"

    const memberQueries = useQueries({
        queries: members.map(member => ({
            queryKey: ["guildMember", member.uuid],
            queryFn: async () => {
                const response = await fetch(`/api/guildmembers?uuid=${member.uuid}`)
                const data = await response.json() as ApiResponse<PlayerForGuild["player"]>
                if (data.error) {
                    throw new Error(data.message)
                }
                return data.player
            },
            staleTime: 1000 * 60 * 60 * 24
        }))
    })

    const loadedCount = memberQueries.filter(query => !query.isLoading && (query.data || query.isError)).length

    const sortedMembers = [...members].sort((a, b) => {
        if (a.rank === "Guild Master" && b.rank !== "Guild Master") return -1
        if (b.rank === "Guild Master" && a.rank !== "Guild Master") return 1

        const aRank = ranks?.find(rank => rank.name === a.rank)
        const bRank = ranks?.find(rank => rank.name === b.rank)

        const aPriority = aRank?.priority ?? Number.MIN_SAFE_INTEGER
        const bPriority = bRank?.priority ?? Number.MIN_SAFE_INTEGER

        if (aPriority !== bPriority) {
            return bPriority - aPriority
        }

        return a.uuid.localeCompare(b.uuid)
    })

    useEffect(() => {
        if (!hasShownToast.current && totalMembers > 0) {
            toast.loading(`Loading guild members... (0/${totalMembers})`, {
                id: TOAST_ID,
                duration: 1000
            })
            hasShownToast.current = true
        }
    }, [totalMembers, TOAST_ID])

    useEffect(() => {
        if (loadedCount > 0) {
            if (loadedCount >= totalMembers) {
                toast.success(`Loaded all ${totalMembers} guild members!`, {
                    id: TOAST_ID
                })
            } else {
                toast.loading(`Loading guild members... (${loadedCount}/${totalMembers})`, {
                    id: TOAST_ID
                })
            }
        }
    }, [loadedCount, totalMembers, TOAST_ID])

    return (
        <Card>
            <CardContent>
                <Table>
                    <TableHeader>
                        <TableRow>
                            <TableHead></TableHead>
                            <TableHead>Name</TableHead>
                            <TableHead>Rank</TableHead>
                            <TableHead>Weekly GEXP</TableHead>
                            <TableHead>Joined Since</TableHead>
                        </TableRow>
                    </TableHeader>
                    <TableBody className="space-y-4">
                        {sortedMembers.map((member) => {
                            const query = memberQueries[members.findIndex(m => m.uuid === member.uuid)]

                            if (query.isLoading || (!query.data && !query.isError)) return null
                            if (query.isError || !query.data) return null

                            const memberWithPlayer: MemberWithPlayer = {
                                ...member,
                                player: query.data,
                                loading: query.isLoading,
                                error: query.isError
                            }

                            return <MemberCard key={member.uuid} member={memberWithPlayer} />
                        })}
                    </TableBody>
                </Table>
            </CardContent>
        </Card>
    )
}

function MemberCard({ member: m }: { member: MemberWithPlayer }) {
    return (
        <TableRow>
            <TableCell>
                <Link href={`https://namemc.com/profile/${m.uuid}`}>
                    <Image
                        src={head(m.uuid, 32)}
                        width={32}
                        height={32}
                        alt={`${m.player?.displayname}'s head`}
                        unoptimized
                        className="shadow-2xl"
                    />
                </Link>
            </TableCell>
            <TableCell>
                <Link href={`/player/${m.player?.displayname}`} prefetch={false}>
                    <PlayerRank
                        rank={m.player?.newPackageRank}
                        monthly={m.player?.monthlyPackageRank}
                        rankColor={m.player?.monthlyRankColor}
                        specialRank={m.player?.rank}
                        prefix={m.player?.prefix}
                        plusColor={m.player?.rankPlusColor}
                    />{" "}
                    <PlayerIGN
                        ign={m.player!.displayname}
                        rank={m.player?.newPackageRank}
                        monthly={m.player?.monthlyPackageRank}
                        rankColor={m.player?.monthlyRankColor}
                        specialRank={m.player?.rank}
                        prefix={m.player?.prefix}
                    />
                </Link>
            </TableCell>
            <TableCell>{m.rank}</TableCell>
            <TableCell>{formatNumber(Object.values(m.expHistory).reduce((a, b) => a + b))}</TableCell>
            <TableCell>{formatDate(m.joined)}</TableCell>
        </TableRow>
    )
}
