"use client"

import { Card, CardContent } from "@/components/ui/card"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { getColor } from "@/lib/colors"
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 z from "zod"

type PlayerForGuild = z.infer<typeof playerForGuildSchema>
import Image from "next/image"
import Link from "next/link"
import { useEffect, useState } from "react"
import { toast } from "sonner"

type MemberWithPlayer = Guild["guild"]["members"][number] & {
    player?: PlayerForGuild["player"]
    loading?: boolean
    error?: boolean
}

export function GuildMembers({ members: mem, ranks }: { members: Guild["guild"]["members"], ranks: Guild["guild"]["ranks"] }) {
    const [members, setMembers] = useState<MemberWithPlayer[]>(
        mem.map(member => ({ ...member, loading: false, error: false }))
    )
    const [currentIndex, setCurrentIndex] = useState(0)
    const [isLoading, setIsLoading] = useState(false)

    const fetchMemberData = async (uuid: string, index: number) => {
        setMembers(prev => prev.map((member, i) => i === index ? { ...member, loading: true } : member))

        try {
            const response = await fetch(`/api/guildmembers?uuid=${uuid}`)
            const data = await response.json()

            if (data.error) {
                setMembers(prev => prev.map((member, i) => i === index ? { ...member, loading: false, error: true } : member))
            } else {
                setMembers(prev => prev.map((member, i) => i === index ? { ...member, loading: false, player: data.player } : member))
            }
        } catch {
            setMembers(prev => prev.map((member, i) => i === index ? { ...member, loading: false, error: true } : member))
        }
    }

    useEffect(() => {
        if (currentIndex < members.length && !isLoading) {
            const timer = setTimeout(() => {
                setIsLoading(true)
                fetchMemberData(members[currentIndex].uuid, currentIndex).then(() => {
                    setCurrentIndex(prev => prev + 1)
                    setIsLoading(false)
                })
            }, 100)

            return () => clearTimeout(timer)
        }
    }, [currentIndex, members, isLoading])

    toast.info(`Loaded ${members.filter(member => member.player).length} out of ${members.length} guild members`, {
        id: "guild.members.loader",
        duration: 1000
    })

    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">
                        {members.filter(member => member.player).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)
                        }).map((member, i) => <MemberCard key={i} member={member} />)}
                    </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>
                <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}
                />
            </TableCell>
            <TableCell>{m.rank}</TableCell>
            <TableCell>{formatNumber(Object.values(m.expHistory).reduce((a, b) => a + b))}</TableCell>
            <TableCell>{formatDate(m.joined)}</TableCell>
        </TableRow>
    )
}

function PlayerIGN(
    { ign, rank, monthly, rankColor, specialRank, prefix }: {
        ign: string
        rank: string | undefined
        monthly: string | undefined
        rankColor: string | undefined
        specialRank: string | undefined
        prefix: string | undefined
    }
) {
    if (prefix === "[PIG+++]") {
        return <span className="text-mc-light-purple">{ign}</span>
    }

    if (specialRank) {
        if (specialRank === "YOUTUBER") {
            return <span className="text-mc-red">{ign}</span>
        }

        if (specialRank === "STAFF") {
            return <span className="text-mc-red">{ign}</span>
        }
    }

    if (monthly === "SUPERSTAR") {
        if (rankColor === "GOLD") {
            return <span className="text-mc-gold">{ign}</span>
        } else {
            return <span className="text-mc-aqua">{ign}</span>
        }
    }

    switch (rank) {
        case "VIP":
            return <span className="text-mc-green">{ign}</span>
        case "VIP_PLUS":
            return <span className="text-mc-green">{ign}</span>
        case "MVP":
            return <span className="text-mc-aqua">{ign}</span>
        case "MVP_PLUS":
            return <span className="text-mc-aqua">{ign}</span>
        default:
            return <span className="text-mc-gray">{ign}</span>
    }
}

function PlayerRank(
    { rank, monthly, plusColor, rankColor, specialRank, prefix }: {
        rank: string | undefined
        monthly: string | undefined
        plusColor?: string
        rankColor: string | undefined
        specialRank: string | undefined
        prefix: string | undefined
    }
) {
    if (prefix === "[PIG+++]") {
        return (
            <>
                <span className="text-mc-light-purple">[PIG</span>
                <span className="text-mc-aqua">+++</span>
                <span className="text-mc-light-purple">]</span>
            </>
        )
    }

    if (specialRank) {
        if (specialRank === "YOUTUBER") {
            return (
                <>
                    <span className="text-mc-red">[</span>
                    <span className="text-mc-white">YOUTUBE</span>
                    <span className="text-mc-red">]</span>
                </>
            )
        }

        if (specialRank === "STAFF") {
            return (
                <>
                    <span className="text-mc-red">[</span>
                    <span className="text-mc-gold">ዞ</span>
                    <span className="text-mc-red">]</span>
                </>
            )
        }
    }

    if (monthly === "SUPERSTAR") {
        if (rankColor === "GOLD") {
            return (
                <>
                    <span className="text-mc-gold">[MVP</span>
                    <span className={getColor(plusColor)}>++</span>
                    <span className="text-mc-gold">]</span>
                </>
            )
        } else {
            return (
                <>
                    <span className="text-mc-aqua">[MVP</span>
                    <span className={getColor(plusColor)}>++</span>
                    <span className="text-mc-aqua">]</span>
                </>
            )
        }
    }

    switch (rank) {
        case "VIP":
            return <span className="text-mc-green">[VIP]</span>
        case "VIP_PLUS":
            return (
                <>
                    <span className="text-mc-green">[VIP</span>
                    <span className="text-mc-gold">+</span>
                    <span className="text-mc-green">]</span>
                </>
            )
        case "MVP":
            return <span className="text-mc-aqua">[MVP]</span>
        case "MVP_PLUS":
            return (
                <>
                    <span className="text-mc-aqua">[MVP</span>
                    <span className={getColor(plusColor)}>+</span>
                    <span className="text-mc-aqua">]</span>
                </>
            )
        default:
            return null
    }
}
