"use client"

import { useState, useRef, useLayoutEffect } from "react"
import { motion, AnimatePresence } from "framer-motion"
import { User } from "lucide-react"
import Image from "next/image"
import { useRevelationInView } from "@/lib/panel-reveal"
import { useTranslations } from "next-intl"

interface Director {
  name: string
  titleKey?: string
  title?: string
  departmentKey?: string
  department?: string
  email?: string
  phone?: string
  photo: string
  subordinates?: Director[]
}

const getOrgData = (_tTitles: any, _tDepartments: any): Director => ({
  name: "Mamadou Abib DIOP",
  titleKey: "directorGeneral",
  departmentKey: "generalManagement",
  email: "dg@sar.sn",
  photo: "/media/directeurs/mamadou-abib-diop.jpg",
  subordinates: [
    {
      name: "Daouda KEBE",
      titleKey: "executiveDirectorOperations",
      departmentKey: "operations",
      email: "d.kebe@sar.sn",
      photo: "/media/directeurs/daouda-kebe.jpg",
      subordinates: [
        {
          name: "Ousmane SEMBENE",
          titleKey: "directorTechnical",
          departmentKey: "technical",
          email: "o.sembene@sar.sn",
          photo: "/media/directeurs/ousmane-sembene.jpg",
        },
        {
          name: "Maimouna DIOP DIAGNE",
          titleKey: "directorCommercialMarketing",
          departmentKey: "commercial",
          email: "m.diop@sar.sn",
          photo: "/media/directeurs/maimouna-diop.jpg",
        },
        {
          name: "Cheikh Sidi Yahya LY",
          titleKey: "directorQHSE",
          departmentKey: "qhse",
          email: "c.ly@sar.sn",
          photo: "/media/directeurs/cheikh-ly.jpg",
        },
      ],
    },
    {
      name: "Oumy FALL",
      titleKey: "directorStrategy",
      departmentKey: "strategy",
      photo: "/media/directeurs/oumy-fall.jpg",
    },
    {
      name: "Moustapha NDIAYE",
      titleKey: "directorLegal",
      departmentKey: "legal",
      photo: "/media/directeurs/moustapha-ndiaye.jpg",
    },
    {
      name: "Cheikh Tidiane MBODJI",
      titleKey: "advisorDG",
      departmentKey: "generalManagement",
      photo: "/media/directeurs/cheikh-tidiane-mbodji.jpg",
    },
    {
      name: "Papa Moctar DIOP",
      titleKey: "advisorDG",
      departmentKey: "generalManagement",
      photo: "/media/directeurs/papa-moctar-diop.jpg",
    },
    {
      name: "Souleymane SECK",
      titleKey: "executiveDirectorSupport",
      departmentKey: "support",
      email: "s.seck@sar.sn",
      photo: "/media/directeurs/souleymane-seck.jpg",
      subordinates: [
        {
          name: "Idrissa CISSE",
          titleKey: "directorInformationSystemsTNI",
          departmentKey: "it",
          email: "i.cisse@sar.sn",
          photo: "/media/directeurs/idrissa-cisse.jpg",
        },
        {
          name: "Oumar DIOUF",
          titleKey: "directorHumanResources",
          departmentKey: "hr",
          email: "o.diouf@sar.sn",
          photo: "/media/directeurs/oumar-diouf.jpg",
        },
        {
          name: "Oumar Yaya SOW",
          titleKey: "directorFinancialAccounting",
          departmentKey: "finance",
          email: "o.sow@sar.sn",
          photo: "/media/directeurs/oumar-yaya-sow.jpg",
        },
      ],
    },
  ],
})

// ── Carte personne (style État des lieux) ────────────────────────────────────
function PersonCard({ person, level = 0, widthClass }: { person: Director; level?: number; widthClass?: string }) {
  const hasPhoto = person.photo && person.photo !== "/placeholder.svg"

  const defaultWidth =
    level === 0 ? "w-48 sm:w-52 md:w-56"
    : "w-36 sm:w-40 md:w-44"

  const cardWidth = widthClass ?? defaultWidth

  const nameSize =
    level === 0 ? "text-sm font-bold"
    : level === 1 ? "text-xs font-bold"
    : "text-xs font-semibold"

  return (
    <motion.div className={`flex flex-col ${cardWidth}`}>
      {/* Photo */}
      <div className={`border-2 border-gray-400 bg-gray-100 overflow-hidden w-full ${
        level === 0 ? "aspect-[3/3.2]" : "aspect-square"
      }`}>
        {hasPhoto ? (
          <Image
            src={person.photo}
            alt={person.name}
            width={224}
            height={224}
            className="w-full h-full object-cover object-top"
          />
        ) : (
          <div className="w-full h-full flex items-center justify-center bg-gray-50">
            <User
              className={`text-gray-300 ${
                level === 0 ? "w-16 h-16" : level === 1 ? "w-12 h-12" : "w-9 h-9"
              }`}
            />
          </div>
        )}
      </div>

      {/* Infos */}
      <div className="border-2 border-t-0 border-gray-400 bg-white px-3 py-2.5">
        {person.title && (
          <>
            <p className="text-[9px] font-semibold uppercase tracking-widest text-gray-400 leading-tight">
              {person.title}
            </p>
            <div className="h-0.5 w-6 bg-primary/70 mt-0.5 mb-1.5" aria-hidden />
          </>
        )}
        <p className={`text-gray-900 leading-snug ${nameSize}`}>{person.name}</p>
      </div>
    </motion.div>
  )
}

// ── DirectorCard (arbre hiérarchique) ────────────────────────────────────────
function DirectorCard({ director, level = 0 }: { director: Director; level?: number }) {
  const [isExpanded] = useState(true)
  const hasSubordinates = director.subordinates && director.subordinates.length > 0
  const [ref, inView] = useRevelationInView({ triggerOnce: true, threshold: 0.1 })
  const containerRef = useRef<HTMLDivElement>(null)
  const firstElementRef = useRef<HTMLDivElement>(null)
  const lastElementRef = useRef<HTMLDivElement>(null)
  const gridRef = useRef<HTMLDivElement>(null)
  const [lineStyle, setLineStyle] = useState<{ left: string; width: string } | null>(null)
  const [verticalLinesHeight, setVerticalLinesHeight] = useState<number>(0)

  useLayoutEffect(() => {
    if (!hasSubordinates || !isExpanded) return

    const calculateLinePosition = () => {
      if (!containerRef.current) return

      if (director.subordinates!.length >= 2 && gridRef.current && gridRef.current.children.length >= 2) {
        const containerRect = containerRef.current.getBoundingClientRect()
        const children = Array.from(gridRef.current.children) as HTMLElement[]
        let leftmostCenter = Infinity
        let rightmostCenter = -Infinity
        for (const child of children) {
          const rect = child.getBoundingClientRect()
          const centerX = rect.left - containerRect.left + rect.width / 2
          if (centerX < leftmostCenter) leftmostCenter = centerX
          if (centerX > rightmostCenter) rightmostCenter = centerX
        }
        const width = rightmostCenter - leftmostCenter
        if (width > 0 && Number.isFinite(leftmostCenter) && Number.isFinite(rightmostCenter)) {
          setLineStyle({ left: `${leftmostCenter}px`, width: `${width}px` })
        } else {
          setLineStyle(null)
        }
      } else {
        setLineStyle(null)
      }

      const containerRect = containerRef.current.getBoundingClientRect()

      if (gridRef.current && gridRef.current.children.length > 0) {
        const firstChild = gridRef.current.children[0] as HTMLElement
        if (firstChild) {
          const firstChildRect = firstChild.getBoundingClientRect()
          const verticalDistance = firstChildRect.top - containerRect.top
          setVerticalLinesHeight(Math.max(8, verticalDistance))
        } else {
          setVerticalLinesHeight(8)
        }
      } else {
        setVerticalLinesHeight(8)
      }
    }

    const t1 = setTimeout(calculateLinePosition, 200)
    const t2 = setTimeout(calculateLinePosition, 400)
    const t3 = setTimeout(calculateLinePosition, 600)
    const t4 = setTimeout(calculateLinePosition, 900)

    window.addEventListener('resize', calculateLinePosition)
    const resizeObserver = new ResizeObserver(calculateLinePosition)
    if (containerRef.current) resizeObserver.observe(containerRef.current)
    if (gridRef.current) resizeObserver.observe(gridRef.current)

    return () => {
      clearTimeout(t1); clearTimeout(t2); clearTimeout(t3); clearTimeout(t4)
      window.removeEventListener('resize', calculateLinePosition)
      resizeObserver.disconnect()
    }
  }, [level, hasSubordinates, isExpanded, director.subordinates])

  return (
    <>
      <div className="relative flex flex-col items-center w-full overflow-visible" style={{ paddingBottom: '1.5rem' }}>
        <motion.div
          ref={ref}
          initial={{ opacity: 0, y: 16 }}
          animate={inView ? { opacity: 1, y: 0 } : {}}
          transition={{ duration: 0.5, delay: level * 0.05 }}
          className="relative"
        >
          <PersonCard person={director} level={level} />

          {/* Trait de liaison vers la barre horizontale des subordonnés.
              Sa hauteur est exactement la marge haute du conteneur des
              subordonnés (mt-14 sm, mt-16 md) : il part du bas de la carte et
              vient toucher la barre, sans mesure au moment du rendu.
              Ces deux valeurs sont donc couplées, changer `mt-*` sur le
              conteneur impose de reporter la hauteur ici. */}
          {hasSubordinates && (
            <div
              aria-hidden
              className="absolute left-1/2 top-full -translate-x-1/2 hidden h-14 w-0.5 bg-gray-400 sm:block md:h-16 z-10"
            />
          )}
        </motion.div>

        {/* Subordonnés */}
        <AnimatePresence>
          {hasSubordinates && isExpanded && (
            <motion.div
              ref={containerRef}
              initial={{ opacity: 0, height: 0 }}
              animate={{ opacity: 1, height: "auto" }}
              exit={{ opacity: 0, height: 0 }}
              transition={{ duration: 0.4, ease: "easeInOut" }}
              className="relative w-full mt-10 sm:mt-14 md:mt-16 overflow-visible"
            >
              {/* Ligne horizontale */}
              {lineStyle && (
                <motion.div
                  initial={{ scaleX: 0 }}
                  animate={{ scaleX: 1 }}
                  transition={{ duration: 0.4, delay: 0.2 }}
                  className="absolute top-0 bg-gray-400 hidden sm:block z-10"
                  style={{
                    left: lineStyle.left,
                    width: lineStyle.width,
                    height: '2px',
                    top: '0px',
                    transform: 'translateX(0)',
                  }}
                />
              )}

              {/* Grille subordonnés, flex-row : tous au même niveau sur une seule ligne */}
              {(() => {
                return (
                  <div
                    ref={gridRef}
                    className={`flex flex-row flex-nowrap justify-center ${level === 0 ? "gap-5 sm:gap-6 lg:gap-8" : "gap-6 sm:gap-8"} pt-6 sm:pt-8 md:pt-10 lg:pt-12 relative`}
                  >
                    {director.subordinates!.map((sub, index) => {
                      const isFirst = index === 0
                      const isLast = index === director.subordinates!.length - 1
                      const itemRef = isFirst ? firstElementRef : isLast ? lastElementRef : null
                      return (
                        <motion.div
                          key={index}
                          ref={itemRef}
                          initial={{ opacity: 0, y: 20 }}
                          animate={{ opacity: 1, y: 0 }}
                          transition={{ duration: 0.4, delay: 0.1 * index }}
                          className={`relative flex flex-col items-center flex-shrink-0 overflow-visible ${level === 0 ? "w-36 sm:w-40 md:w-44" : ""}`}
                        >
                          {/* Ligne verticale descente */}
                          {verticalLinesHeight > 0 && (
                            <motion.div
                              initial={{ scaleY: 0 }}
                              animate={{ scaleY: 1 }}
                              transition={{ duration: 0.3, delay: 0.2 + index * 0.05 }}
                              className="absolute left-1/2 -translate-x-1/2 bg-gray-400 hidden sm:block z-0"
                              style={{
                                top: `-${verticalLinesHeight}px`,
                                height: `${verticalLinesHeight}px`,
                                width: '2px',
                                transformOrigin: 'bottom',
                              }}
                            />
                          )}
                          <DirectorCard director={sub} level={level + 1} />
                        </motion.div>
                      )
                    })}
                  </div>
                )
              })()}
            </motion.div>
          )}
        </AnimatePresence>
      </div>
    </>
  )
}

// ── Export principal ─────────────────────────────────────────────────────────
export default function OrgChart() {
  const tTitles = useTranslations('organigram.titles')
  const tDepartments = useTranslations('organigram.departments')
  const [ref, inView] = useRevelationInView({ triggerOnce: true, threshold: 0.1 })

  const orgData = getOrgData(tTitles, tDepartments)

  const mapTranslations = (director: Director): Director => ({
    ...director,
    title: director.titleKey ? tTitles(director.titleKey) : undefined,
    department: director.departmentKey ? tDepartments(director.departmentKey) : undefined,
    subordinates: director.subordinates?.map(mapTranslations),
  })

  const translatedOrgData = mapTranslations(orgData)

  const flattenDirectorsBFS = (root: Director): Director[] => {
    const result: Director[] = []
    const queue: Director[] = [root]
    while (queue.length > 0) {
      const current = queue.shift()!
      result.push(current)
      if (current.subordinates) queue.push(...current.subordinates)
    }
    return result
  }

  const flatDirectors = flattenDirectorsBFS(translatedOrgData)

  /* ── Arbre ou grille : mesure de l'encombrement horizontal ─────────────────
     Le critère est la LARGEUR seule : si l'arbre tient en entier sur l'axe des
     x, on l'affiche ; sinon on bascule sur la grille de cartes. Jamais d'état
     intermédiaire, jamais d'arbre rogné.
     Deux pièges que la mesure doit contourner :
     1. `offsetWidth` de l'arbre vaut 1 216 px, la largeur de sa rangée de tête,
        alors que les sous-arbres des deux extrémités débordent d'environ 208 px
        de chaque côté en overflow-visible. Il faut donc l'étendue réelle,
        obtenue en prenant l'union des rectangles de tous ses descendants.
     2. La comparaison se fait avec la largeur de la SECTION, pas avec celle du
        conteneur intérieur borné à max-w-7xl : le débordement n'est pas rogné
        avant la section, l'arbre peut donc légitimement déborder du conteneur.
     L'arbre reste monté en permanence, hors flux et invisible quand la grille
     est affichée : c'est ce qui permet de le remesurer au redimensionnement et
     de revenir à lui dès qu'il tient. Les photos étant les mêmes dans les deux
     vues, ce doublon ne coûte aucune requête supplémentaire. */
  const [mode, setMode] = useState<"arbre" | "cartes">("cartes")
  const sectionRef = useRef<HTMLElement>(null)
  const arbreRef = useRef<HTMLDivElement>(null)

  useLayoutEffect(() => {
    const evaluer = () => {
      const section = sectionRef.current
      const arbre = arbreRef.current
      if (!section || !arbre) return

      let gauche = Infinity
      let droite = -Infinity
      for (const noeud of arbre.querySelectorAll<HTMLElement>("*")) {
        const r = noeud.getBoundingClientRect()
        if (r.width === 0) continue
        if (r.left < gauche) gauche = r.left
        if (r.right > droite) droite = r.right
      }
      if (!Number.isFinite(gauche) || !Number.isFinite(droite)) return

      setMode(droite - gauche <= section.clientWidth ? "arbre" : "cartes")
    }

    evaluer()
    window.addEventListener("resize", evaluer)
    const ro = new ResizeObserver(evaluer)
    if (sectionRef.current) ro.observe(sectionRef.current)
    // Les photos modifient l'encombrement en arrivant : on remesure après coup.
    const t = setTimeout(evaluer, 700)
    return () => {
      window.removeEventListener("resize", evaluer)
      ro.disconnect()
      clearTimeout(t)
    }
  }, [])

  return (
    // Aucun rembourrage haut : l'organigramme démarre au ras de la barre
    // d'onglets de /entreprise, l'écart est fixé par la section qui l'accueille.
    <section
      // Deux refs sur le même nœud : celui de la révélation, qui est un callback,
      // et celui de la mesure. React 19 exige que le callback ne retourne rien.
      ref={(el) => {
        ref(el)
        sectionRef.current = el
      }}
      className="pt-0 pb-0 bg-white relative overflow-hidden w-full flex justify-center"
    >
      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10 w-full">

        {/* Grille de cartes : affichée dès que l'arbre ne tient pas en entier */}
        {mode === "cartes" && (
          <motion.div
            initial={{ opacity: 0, y: 20 }}
            animate={inView ? { opacity: 1, y: 0 } : {}}
            transition={{ duration: 0.5 }}
            className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4"
          >
            {flatDirectors.map((director, index) => (
              <motion.div
                key={`${director.name}-${index}`}
                initial={{ opacity: 0, y: 10 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ delay: index * 0.04 }}
              >
                <PersonCard person={director} level={1} widthClass="w-full" />
              </motion.div>
            ))}
          </motion.div>
        )}

        {/* Arbre complet. `w-max` lui donne sa largeur naturelle, ce qui rend la
            mesure possible ; hors mode arbre il sort du flux et devient
            invisible, sans disparaître du DOM. */}
        <div
          ref={arbreRef}
          aria-hidden={mode !== "arbre"}
          className={
            mode === "arbre"
              ? "w-max mx-auto"
              : "w-max pointer-events-none absolute left-0 top-0 -z-10 opacity-0"
          }
        >
          <motion.div
            initial={{ opacity: 0, y: 16 }}
            animate={inView ? { opacity: 1, y: 0 } : {}}
            transition={{ duration: 0.6 }}
            className="flex justify-center items-center"
          >
            <DirectorCard director={translatedOrgData} />
          </motion.div>
        </div>

      </div>
    </section>
  )
}
