import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Box, Typography } from '@mui/material'
import { useNavigate } from 'react-router'
import type { AgentDirectoryEntry, AgentLevel } from '../../domain/agentDirectory'
import { AGENT_LEVEL_ORDER } from '../../domain/agentDirectory'
import { agentDirectory } from '../../mock-data/agentDirectory'
import { AgentRing } from './AgentRing'
import { AgentPreviewPopover } from './AgentPreviewPopover'
import { RING_SPECS, RING_REFERENCE_PX } from './agentRingConfig'
import { ROUTES } from '../../lib/constants'
import { BADGE_COLORS, DS_TEXT } from '../../lib/ds'

interface Props {
  /** Bis zu welcher Stufe die Ringe sichtbar sind — kumulativ. */
  level: AgentLevel
}

/** Misst die Containerbreite, damit Portraits und Schrift mitskalieren. */
function useContainerWidth(): [React.RefObject<HTMLDivElement | null>, number] {
  const ref = useRef<HTMLDivElement | null>(null)
  const [width, setWidth] = useState(RING_REFERENCE_PX)

  useEffect(() => {
    const node = ref.current
    if (!node) return

    // Ohne ResizeObserver bleibt die Referenzbreite stehen: die Darstellung ist
    // dann nicht mitskaliert, aber vollständig bedienbar. Ein harter Absturz
    // wegen einer fehlenden Browser-Schnittstelle wäre die schlechtere Antwort.
    if (typeof ResizeObserver === 'undefined') {
      setWidth(node.getBoundingClientRect().width || RING_REFERENCE_PX)
      return
    }

    const observer = new ResizeObserver(([entry]) => {
      setWidth(entry.contentRect.width)
    })
    observer.observe(node)
    return () => observer.disconnect()
  }, [])

  return [ref, width]
}

/**
 * Kreisförmige Darstellung der digitalen Belegschaft.
 *
 * Aufbau nach der Referenzgrafik: Kernteam innen und gold gerahmt, danach die
 * Zentralen Dienste, aussen die Spezialisten der Geschäftsbereiche. Welche Ringe
 * sichtbar sind, bestimmt die gewählte Stufe — kumulativ, wie im Konzept.
 *
 * Nicht sichtbare Ringe werden ausgeblendet statt entfernt: so bleibt die
 * Bewegung beim Stufenwechsel ruhig und der Kreis springt nicht in der Grösse.
 */
export function TeamOverviewRing({ level }: Props) {
  const navigate = useNavigate()
  const [ref, width] = useContainerWidth()
  const [preview, setPreview] = useState<AgentDirectoryEntry | null>(null)
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)

  const scale = width / RING_REFERENCE_PX
  const visibleUpTo = AGENT_LEVEL_ORDER.indexOf(level)

  const agentsByLevel = useMemo(() => {
    const map = new Map<AgentLevel, AgentDirectoryEntry[]>()
    for (const spec of RING_SPECS) {
      map.set(spec.level, agentDirectory.filter(a => a.level === spec.level))
    }
    return map
  }, [])

  const handleSelect = useCallback(
    (agent: AgentDirectoryEntry, element: HTMLElement | null) => {
      if (agent.isCore) {
        navigate(`${ROUTES.SUPPLY.TEAM_PERSONNEL}/${agent.id}`)
        return
      }
      setPreview(agent)
      setAnchorEl(element)
    },
    [navigate],
  )

  // Der Ringknoten meldet nur den Agenten; das auslösende Element holen wir uns
  // aus dem Fokus, damit die Vorschau am angeklickten Portrait hängt.
  const onNodeSelect = useCallback(
    (agent: AgentDirectoryEntry) => {
      const active = document.activeElement
      handleSelect(agent, active instanceof HTMLElement ? active : null)
    },
    [handleSelect],
  )

  const closePreview = useCallback(() => {
    setPreview(null)
    setAnchorEl(null)
  }, [])

  return (
    <>
      <Box
        ref={ref}
        role="group"
        aria-label="Digitale Belegschaft"
        sx={{
          position: 'relative',
          width: '100%',
          maxWidth: RING_REFERENCE_PX,
          aspectRatio: '1 / 1',
          mx: 'auto',
        }}
      >
        {RING_SPECS.map((spec, index) => (
          <AgentRing
            key={spec.level}
            agents={agentsByLevel.get(spec.level) ?? []}
            spec={spec}
            scale={scale}
            visible={index <= visibleUpTo}
            onSelect={onNodeSelect}
          />
        ))}

        {/* Nabe */}
        <Box
          sx={{
            position: 'absolute',
            left: '50%',
            top: '50%',
            transform: 'translate(-50%, -50%)',
            width: '19%',
            height: '19%',
            borderRadius: '50%',
            bgcolor: DS_TEXT.brand,
            color: DS_TEXT.inverted,
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            justifyContent: 'center',
            textAlign: 'center',
            px: 1,
          }}
        >
          <Typography
            sx={{
              fontWeight: 700,
              letterSpacing: '0.08em',
              fontSize: `${Math.max(9, 13 * scale)}px`,
              lineHeight: 1.2,
            }}
          >
            PROPERTY{' '}
            <Box component="span" sx={{ color: BADGE_COLORS.gold }}>ON</Box>
          </Typography>
          <Typography
            sx={{
              fontWeight: 700,
              fontSize: `${Math.max(20, 40 * scale)}px`,
              lineHeight: 1.05,
              mt: 0.25,
            }}
          >
            {agentDirectory.length}
          </Typography>
          <Typography sx={{ fontSize: `${Math.max(7.5, 10 * scale)}px`, lineHeight: 1.25, opacity: 0.85 }}>
            digitale Mitarbeitende
          </Typography>
        </Box>
      </Box>

      <AgentPreviewPopover agent={preview} anchorEl={anchorEl} onClose={closePreview} />
    </>
  )
}
