import { Badge, Box, Flex, Grid, Spinner, Stack, Text } from '@chakra-ui/react'
import { Award, Calendar, Target, TrendingUp } from 'lucide-react'
import type { ReactNode } from 'react'
import { useEffect, useState } from 'react'
import { useNavigate, useOutletContext } from 'react-router-dom'
import { CalledItAvatar, CalledItButton, CalledItCard } from '../components'
import { fetchBets, type BetResponse } from '../features/bets/betApi'
import { fetchLeaderboard, type LeaderboardResult } from '../features/leaderboard/leaderboardApi'
import { fetchMatches, type MatchResponse } from '../features/matches/matchApi'
import { teamLogoUrl } from '../features/teams/teamApi'
import type { AppOutletContext } from '../types/auth'
import { formatDateTime } from '../utils/dateFormat'

function rankPalette(rank: number): string {
  if (rank === 1) return 'yellow'
  if (rank === 2) return 'gray'
  if (rank === 3) return 'orange'
  return 'brand'
}

function StatCard({ icon, label, value, sub }: { icon: ReactNode; label: string; value: string; sub: string }) {
  return (
    <Box borderWidth="1px" borderColor="border" bg="panel" rounded="2xl" px="5" py="4" shadow="xs">
      <Flex align="center" gap="2" mb="2" color="muted">
        {icon}
        <Text fontSize="xs" fontWeight="600" textTransform="uppercase" letterSpacing="0.06em">
          {label}
        </Text>
      </Flex>
      <Text fontSize="2xl" fontWeight="800" color="heading" lineHeight="1">
        {value}
      </Text>
      <Text fontSize="xs" color="muted" mt="1">
        {sub}
      </Text>
    </Box>
  )
}

export function MainPage() {
  const { session, selectedCompetitionId } = useOutletContext<AppOutletContext>()
  const navigate = useNavigate()
  const competitionId = selectedCompetitionId ? Number(selectedCompetitionId) : null

  const [matches, setMatches] = useState<MatchResponse[]>([])
  const [bets, setBets] = useState<BetResponse[]>([])
  const [leaderboard, setLeaderboard] = useState<LeaderboardResult | null>(null)
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    if (!competitionId) return
    setLoading(true)
    Promise.all([
      fetchMatches(session.token, competitionId),
      fetchBets(session.token, competitionId),
      fetchLeaderboard(session.token, competitionId),
    ])
      .then(([m, b, l]) => {
        setMatches(m)
        setBets(b)
        setLeaderboard(l)
        setLoading(false)
      })
      .catch(() => setLoading(false))
  }, [session.token, competitionId])

  if (!selectedCompetitionId) {
    return (
      <CalledItCard cardTitle={`Welcome back, ${session.username}`}>
        <Text color="muted">Select a competition from the header to see your dashboard.</Text>
      </CalledItCard>
    )
  }

  if (loading) {
    return (
      <CalledItCard cardTitle="Dashboard">
        <Flex justify="center" py="10">
          <Spinner />
        </Flex>
      </CalledItCard>
    )
  }

  const betMap = new Set(bets.map((b) => b.matchId))
  const now = Date.now()

  const upcomingUnbet = matches
    .filter((m) => new Date(m.matchDate).getTime() > now + 60 * 1000 && !betMap.has(m.id))
    .sort((a, b) => a.matchDate.localeCompare(b.matchDate))
    .slice(0, 5)

  const allEntries = leaderboard?.entries ?? []
  const myEntry = leaderboard?.currentUserEntry ?? allEntries.find((e) => e.username === session.username)
  const evaluatedBets = bets.filter((b) => b.points !== null)
  const totalPoints = evaluatedBets.reduce((sum, b) => sum + (b.points ?? 0), 0)
  const avgPoints =
    evaluatedBets.length > 0 ? (totalPoints / evaluatedBets.length).toFixed(1) : '—'

  const topPlayers = allEntries.slice(0, 5)
  const myRankOutsideTop5 = myEntry && myEntry.rank > 5

  return (
    <Stack gap="5">
      {/* Stat cards */}
      <Grid templateColumns={{ base: 'repeat(2, 1fr)', md: 'repeat(4, 1fr)' }} gap="4">
        <StatCard
          icon={<Award size={16} />}
          label="Your Rank"
          value={myEntry ? `#${myEntry.rank}` : '—'}
          sub={`of ${allEntries.length} players`}
        />
        <StatCard
          icon={<TrendingUp size={16} />}
          label="Total Points"
          value={myEntry ? String(myEntry.totalPoints) : '0'}
          sub="in this competition"
        />
        <StatCard
          icon={<Target size={16} />}
          label="Avg pts / Bet"
          value={avgPoints}
          sub={`${evaluatedBets.length} evaluated`}
        />
        <StatCard
          icon={<Calendar size={16} />}
          label="Bets Placed"
          value={myEntry ? String(myEntry.betsPlaced) : String(bets.length)}
          sub={`of ${matches.length} matches`}
        />
      </Grid>

      <Grid templateColumns={{ base: '1fr', md: '1fr 1fr' }} gap="4" alignItems="start">
        {/* Unbet upcoming matches */}
        <CalledItCard cardTitle="Place Your Bets">
          {upcomingUnbet.length === 0 ? (
            <Text color="muted" fontSize="sm">
              All upcoming matches have bets placed — nice work!
            </Text>
          ) : (
            <Stack gap="3">
              {upcomingUnbet.map((match) => (
                <Stack
                  key={match.id}
                  px="3"
                  py="2"
                  borderWidth="1px"
                  borderColor="border"
                  rounded="xl"
                  bg="subtle"
                  gap="1"
                >
                  <Text fontSize="xs" color="muted" textAlign="center">
                    {formatDateTime(match.matchDate)}
                  </Text>
                  <Flex align="center" justify="center" gap="2">
                    <Flex align="center" gap="2" flex="1" justify="flex-end" minW="0">
                      <Text
                        fontWeight="600"
                        color="heading"
                        fontSize="sm"
                        textAlign="right"
                        truncate
                      >
                        {match.homeTeam.name}
                      </Text>
                      <CalledItAvatar
                        src={teamLogoUrl(match.homeTeam.logoUrl)}
                        name={match.homeTeam.name}
                        size="xs"
                        flexShrink={0}
                      />
                    </Flex>
                    <Text fontSize="xs" color="muted" fontWeight="600" minW="5" textAlign="center">
                      vs
                    </Text>
                    <Flex align="center" gap="2" flex="1" justify="flex-start" minW="0">
                      <CalledItAvatar
                        src={teamLogoUrl(match.awayTeam.logoUrl)}
                        name={match.awayTeam.name}
                        size="xs"
                        flexShrink={0}
                      />
                      <Text
                        fontWeight="600"
                        color="heading"
                        fontSize="sm"
                        textAlign="left"
                        truncate
                      >
                        {match.awayTeam.name}
                      </Text>
                    </Flex>
                  </Flex>
                </Stack>
              ))}
              <CalledItButton
                variant="subtle"
                size="sm"
                colorPalette="brand"
                onClick={() => navigate('/matches')}
              >
                Go to Matches
              </CalledItButton>
            </Stack>
          )}
        </CalledItCard>

        {/* Mini leaderboard */}
        <CalledItCard cardTitle="Top Players">
          {topPlayers.length === 0 ? (
            <Text color="muted" fontSize="sm">
              No bets have been evaluated yet.
            </Text>
          ) : (
            <Stack gap="2">
              {topPlayers.map((entry) => {
                const isMe = entry.username === session.username
                return (
                  <Flex
                    key={entry.username}
                    align="center"
                    gap="3"
                    px="3"
                    py="2"
                    borderWidth="1px"
                    borderColor={isMe ? 'colorPalette.200' : 'border'}
                    colorPalette="brand"
                    rounded="xl"
                    bg={isMe ? 'colorPalette.50' : 'subtle'}
                  >
                    <Badge
                      colorPalette={rankPalette(entry.rank)}
                      variant="subtle"
                      minW="7"
                      textAlign="center"
                    >
                      {entry.rank}
                    </Badge>
                    <Flex flex="1" align="center" gap="2" minW="0">
                      <Text
                        fontWeight={isMe ? '700' : '400'}
                        fontSize="sm"
                        color="heading"
                        truncate
                      >
                        {entry.username}
                      </Text>
                      {isMe && (
                        <Badge colorPalette="brand" variant="solid" fontSize="2xs" flexShrink={0}>
                          You
                        </Badge>
                      )}
                    </Flex>
                    <Text fontWeight="700" fontSize="sm" color="heading">
                      {entry.totalPoints}{' '}
                      <Text as="span" fontWeight="400" color="muted" fontSize="xs">
                        pts
                      </Text>
                    </Text>
                  </Flex>
                )
              })}

              {myRankOutsideTop5 && (
                <>
                  <Text textAlign="center" color="muted" fontSize="xs">
                    • • •
                  </Text>
                  <Flex
                    align="center"
                    gap="3"
                    px="3"
                    py="2"
                    borderWidth="1px"
                    borderColor="colorPalette.200"
                    colorPalette="brand"
                    rounded="xl"
                    bg="colorPalette.50"
                  >
                    <Badge colorPalette="brand" variant="subtle" minW="7" textAlign="center">
                      {myEntry.rank}
                    </Badge>
                    <Flex flex="1" align="center" gap="2" minW="0">
                      <Text fontWeight="700" fontSize="sm" color="heading" truncate>
                        {myEntry.username}
                      </Text>
                      <Badge colorPalette="brand" variant="solid" fontSize="2xs" flexShrink={0}>
                        You
                      </Badge>
                    </Flex>
                    <Text fontWeight="700" fontSize="sm" color="heading">
                      {myEntry.totalPoints}{' '}
                      <Text as="span" fontWeight="400" color="muted" fontSize="xs">
                        pts
                      </Text>
                    </Text>
                  </Flex>
                </>
              )}
            </Stack>
          )}
        </CalledItCard>
      </Grid>
    </Stack>
  )
}
