import { Flex, IconButton, Stack, Text } from '@chakra-ui/react'
import { Pencil, Plus, Trash2 } from 'lucide-react'
import { useEffect, useMemo, useState } from 'react'
import { Navigate, useOutletContext } from 'react-router-dom'
import { CalledItAlert, CalledItAvatar, CalledItButton, CalledItCard, CalledItConfirmDialog, CalledItDialog, CalledItLogoUpload, CalledItSelect, CalledItTextInput } from '../components'
import { fetchCompetitions, type CompetitionResponse } from '../features/competitions/competitionApi'
import {
  createTeam,
  deleteTeam,
  fetchTeams,
  teamLogoUrl,
  updateTeam,
  uploadTeamLogo,
  type TeamResponse,
} from '../features/teams/teamApi'
import { useToast } from '../hooks/useToast'
import type { AppOutletContext } from '../types/auth'

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

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

  const { toast, showError, dismiss } = useToast()
  const [teams, setTeams] = useState<TeamResponse[]>([])
  const [competitions, setCompetitions] = useState<CompetitionResponse[]>([])
  const [selectedCompetitionId, setSelectedCompetitionId] = useState<string>('')
  const [searchQuery, setSearchQuery] = useState('')
  const [modalOpen, setModalOpen] = useState(false)
  const [name, setName] = useState('')
  const [nameError, setNameError] = useState<string | undefined>()
  const [editingId, setEditingId] = useState<number | null>(null)
  const [pendingLogo, setPendingLogo] = useState<File | null>(null)
  const [previewUrl, setPreviewUrl] = useState<string | undefined>()
  const [loading, setLoading] = useState(false)
  const [confirmOpen, setConfirmOpen] = useState(false)
  const [pendingDeleteId, setPendingDeleteId] = useState<number | null>(null)

  useEffect(() => {
    fetchCompetitions(session.token)
      .then(setCompetitions)
      .catch((err: unknown) => showError('Failed to load competitions', err instanceof Error ? err.message : String(err)))
  }, [session.token])

  useEffect(() => {
    const competitionId = selectedCompetitionId !== '' ? Number(selectedCompetitionId) : undefined
    fetchTeams(session.token, competitionId)
      .then(setTeams)
      .catch((err: unknown) => showError('Failed to load teams', err instanceof Error ? err.message : String(err)))
  }, [session.token, selectedCompetitionId])

  const filteredTeams = useMemo(() => {
    const q = searchQuery.trim().toLowerCase()
    if (!q) return teams
    return teams.filter((t) => t.name.toLowerCase().includes(q))
  }, [teams, searchQuery])

  function openCreate() {
    setEditingId(null)
    setName('')
    setNameError(undefined)
    setPendingLogo(null)
    setPreviewUrl(undefined)
    setModalOpen(true)
  }

  function openEdit(team: TeamResponse) {
    setEditingId(team.id)
    setName(team.name)
    setNameError(undefined)
    setPendingLogo(null)
    setPreviewUrl(teamLogoUrl(team.logoUrl))
    setModalOpen(true)
  }

  function closeModal() {
    setModalOpen(false)
    setName('')
    setEditingId(null)
    setNameError(undefined)
    setPendingLogo(null)
    setPreviewUrl(undefined)
  }

  function handleLogoSelect(file: File) {
    setPendingLogo(file)
    setPreviewUrl(URL.createObjectURL(file))
  }

  async function handleSubmit() {
    if (!name.trim()) {
      setNameError('Required')
      return
    }

    setLoading(true)
    try {
      let saved: TeamResponse
      if (editingId !== null) {
        saved = await updateTeam(session.token, editingId, name)
      } else {
        saved = await createTeam(session.token, name)
      }

      if (pendingLogo) {
        saved = await uploadTeamLogo(session.token, saved.id, pendingLogo)
      }

      setTeams((prev) =>
        editingId !== null
          ? prev.map((t) => (t.id === saved.id ? saved : t))
          : [...prev, saved],
      )
      closeModal()
    } catch (err: unknown) {
      showError(
        editingId !== null ? 'Failed to update team' : 'Failed to create team',
        err instanceof Error ? err.message : String(err),
      )
    } finally {
      setLoading(false)
    }
  }

  function requestDelete(id: number) {
    setPendingDeleteId(id)
    setConfirmOpen(true)
  }

  async function confirmDelete() {
    if (pendingDeleteId === null) return
    setConfirmOpen(false)
    try {
      await deleteTeam(session.token, pendingDeleteId)
      setTeams((prev) => prev.filter((t) => t.id !== pendingDeleteId))
    } catch (err: unknown) {
      showError('Failed to delete team', err instanceof Error ? err.message : String(err))
    } finally {
      setPendingDeleteId(null)
    }
  }

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

      <CalledItConfirmDialog
        open={confirmOpen}
        onClose={() => { setConfirmOpen(false); setPendingDeleteId(null) }}
        onConfirm={confirmDelete}
        title="Delete Team"
        description="This will permanently delete the team. This action cannot be undone."
      />

      <CalledItDialog
        open={modalOpen}
        onClose={closeModal}
        title={editingId !== null ? 'Edit Team' : 'New Team'}
        footer={
          <Flex gap="2">
            <CalledItButton colorPalette="brand" loading={loading} onClick={handleSubmit}>
              {editingId !== null ? 'Save' : 'Create'}
            </CalledItButton>
            <CalledItButton variant="ghost" onClick={closeModal}>Cancel</CalledItButton>
          </Flex>
        }
      >
        <Stack gap="4">
          <CalledItTextInput
            label="Name"
            value={name}
            errorText={nameError}
            onChange={(e) => { setName(e.target.value); setNameError(undefined) }}
          />
          <CalledItLogoUpload
            currentLogoUrl={previewUrl}
            onFileSelect={handleLogoSelect}
          />
        </Stack>
      </CalledItDialog>

      <CalledItCard cardTitle="Teams">
        <Flex gap="3" mb="3" align="center" justify="space-between">
          <CalledItSelect
            options={[
              { label: 'All competitions', value: '' },
              ...competitions.map((c) => ({ label: c.name, value: String(c.id) })),
            ]}
            value={[selectedCompetitionId]}
            onValueChange={(details) => setSelectedCompetitionId(details.value[0] ?? '')}
            placeholder="All competitions"
          />
          <CalledItButton size="sm" colorPalette="brand" onClick={openCreate}>
            <Plus size={16} /> New Team
          </CalledItButton>
        </Flex>
        <CalledItTextInput
          placeholder="Search teams..."
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          mb="4"
        />
        <Stack gap="2">
          {filteredTeams.length === 0 && (
            <Text color="muted" fontSize="sm">No teams found.</Text>
          )}
          {filteredTeams.map((team) => (
            <Flex key={team.id} align="center" justify="space-between" py="2" borderBottomWidth="1px" borderColor="border">
              <Flex align="center" gap="3">
                <CalledItAvatar src={teamLogoUrl(team.logoUrl)} name={team.name} size="sm" />
                <Text fontWeight="600" color="heading">{team.name}</Text>
              </Flex>
              <Flex gap="1">
                <IconButton size="sm" variant="ghost" aria-label="Edit" onClick={() => openEdit(team)}>
                  <Pencil size={16} />
                </IconButton>
                <IconButton size="sm" variant="ghost" colorPalette="red" aria-label="Delete" onClick={() => requestDelete(team.id)}>
                  <Trash2 size={16} />
                </IconButton>
              </Flex>
            </Flex>
          ))}
        </Stack>
      </CalledItCard>
    </>
  )
}
