import { Field, Flex, IconButton, Input, Stack, Text } from '@chakra-ui/react'
import { Check } from 'lucide-react'
import { useEffect, useState } from 'react'
import { Navigate, useOutletContext } from 'react-router-dom'
import { CalledItAlert, CalledItCard } from '../components'
import { fetchPendingResults, updateMatch, type MatchResponse } from '../features/matches/matchApi'
import { useToast } from '../hooks/useToast'
import { formatDateTime } from '../utils/dateFormat'
import type { AppOutletContext } from '../types/auth'

type ResultDraft = { homeScore: string; awayScore: string }
type DraftErrors = { homeScore?: string; awayScore?: string }

export function AdminPendingResultsPage() {
  const { session } = useOutletContext<AppOutletContext>()

  if (!session.isAdmin) {
    return <Navigate to="/" replace />
  }

  const { toast, showError, dismiss } = useToast()
  const [matches, setMatches] = useState<MatchResponse[]>([])
  const [drafts, setDrafts] = useState<Record<number, ResultDraft>>({})
  const [draftErrors, setDraftErrors] = useState<Record<number, DraftErrors>>({})
  const [saving, setSaving] = useState<Record<number, boolean>>({})

  useEffect(() => {
    fetchPendingResults(session.token)
      .then((data) => {
        setMatches(data)
        const initial: Record<number, ResultDraft> = {}
        data.forEach((m) => { initial[m.id] = { homeScore: '', awayScore: '' } })
        setDrafts(initial)
      })
      .catch((err: unknown) => showError('Failed to load pending results', err instanceof Error ? err.message : String(err)))
  }, [session.token])

  function setDraftField(id: number, field: keyof ResultDraft, value: string) {
    const clamped = value === '' ? '' : String(Math.max(0, Number(value)))
    setDrafts((prev) => ({ ...prev, [id]: { ...prev[id], [field]: clamped } }))
    setDraftErrors((prev) => ({ ...prev, [id]: { ...prev[id], [field]: undefined } }))
  }

  async function handleSave(match: MatchResponse) {
    const draft = drafts[match.id] ?? { homeScore: '', awayScore: '' }
    const errors: DraftErrors = {}
    if (draft.homeScore === '') errors.homeScore = 'Required'
    if (draft.awayScore === '') errors.awayScore = 'Required'

    if (Object.keys(errors).length > 0) {
      setDraftErrors((prev) => ({ ...prev, [match.id]: errors }))
      return
    }

    setSaving((prev) => ({ ...prev, [match.id]: true }))
    try {
      await updateMatch(session.token, match.id, {
        competitionId: match.competitionId,
        homeTeamId: match.homeTeam.id,
        awayTeamId: match.awayTeam.id,
        matchDate: match.matchDate,
        round: match.round,
        homeScore: Number(draft.homeScore),
        awayScore: Number(draft.awayScore),
      })
      setMatches((prev) => prev.filter((m) => m.id !== match.id))
    } catch (err: unknown) {
      showError('Failed to save result', err instanceof Error ? err.message : String(err))
    } finally {
      setSaving((prev) => ({ ...prev, [match.id]: false }))
    }
  }

  return (
    <>
      {toast && (
        <CalledItAlert
          isToast
          status={toast.status}
          title={toast.title}
          description={toast.description}
          onClose={dismiss}
        />
      )}

      <CalledItCard cardTitle="Pending Results">
        {matches.length === 0 && (
          <Text color="muted">No matches are awaiting a result.</Text>
        )}
        <Stack gap="3">
          {matches.map((match) => {
            const errs = draftErrors[match.id] ?? {}
            return (
              <Flex
                key={match.id}
                align="flex-start"
                justify="space-between"
                gap="4"
                px="4"
                py="3"
                borderWidth="1px"
                borderColor="border"
                rounded="xl"
                bg="subtle"
              >
                <Stack gap="0" flex="1" minW="0" pt="1">
                  <Text fontWeight="600" color="heading">
                    {match.homeTeam.name} vs {match.awayTeam.name}
                  </Text>
                  <Text fontSize="sm" color="muted">
                    {formatDateTime(match.matchDate)} · Round {match.round}
                  </Text>
                </Stack>

                <Flex align="flex-start" gap="2" shrink="0">
                  <Field.Root invalid={Boolean(errs.homeScore)}>
                    <Input
                      type="number"
                      min={0}
                      placeholder="0"
                      value={drafts[match.id]?.homeScore ?? ''}
                      onChange={(e) => setDraftField(match.id, 'homeScore', e.target.value)}
                      w="16"
                      textAlign="center"
                      borderColor={errs.homeScore ? 'red.400' : 'border'}
                      bg="white"
                    />
                    {errs.homeScore && <Field.ErrorText fontSize="xs">{errs.homeScore}</Field.ErrorText>}
                  </Field.Root>

                  <Text color="muted" fontWeight="600" pt="2">–</Text>

                  <Field.Root invalid={Boolean(errs.awayScore)}>
                    <Input
                      type="number"
                      min={0}
                      placeholder="0"
                      value={drafts[match.id]?.awayScore ?? ''}
                      onChange={(e) => setDraftField(match.id, 'awayScore', e.target.value)}
                      w="16"
                      textAlign="center"
                      borderColor={errs.awayScore ? 'red.400' : 'border'}
                      bg="white"
                    />
                    {errs.awayScore && <Field.ErrorText fontSize="xs">{errs.awayScore}</Field.ErrorText>}
                  </Field.Root>

                  <IconButton
                    size="sm"
                    colorPalette="brand"
                    aria-label="Save result"
                    loading={saving[match.id]}
                    onClick={() => handleSave(match)}
                    mt="1"
                  >
                    <Check size={16} />
                  </IconButton>
                </Flex>
              </Flex>
            )
          })}
        </Stack>
      </CalledItCard>
    </>
  )
}
