"use client"

import { useMemo, useState, type JSX } from "react"
import { ChevronDown, ChevronRight, GraduationCap, School, Users } from "lucide-react"
import { useTranslations } from "next-intl"

import type { OrgTreeNode } from "../types"
import { cn } from "@/shared/lib/utils"
import { Input } from "@/shared/components/ui/input"

type OrgTreeNavProps = {
  nodes: OrgTreeNode[]
  onSelect?: (node: OrgTreeNode) => void
  selectedId?: string
}

type OrgTreeItemProps = {
  node: OrgTreeNode
  depth: number
  onSelect?: (node: OrgTreeNode) => void
  selectedId?: string
  search: string
}

const NODE_ICON: Record<OrgTreeNode["type"], typeof School> = {
  school: School,
  grade: GraduationCap,
  class: Users,
}

function matchesSearch(node: OrgTreeNode, query: string): boolean {
  if (!query) return true
  if (node.name.toLowerCase().includes(query)) return true
  return (node.children ?? []).some((child) => matchesSearch(child, query))
}

function OrgTreeItem({ node, depth, onSelect, selectedId, search }: OrgTreeItemProps): JSX.Element {
  const [expanded, setExpanded] = useState<boolean>(depth === 0)
  const children = node.children ?? []
  const hasChildren = children.length > 0
  const isSelected = selectedId === node.id
  const Icon = NODE_ICON[node.type]

  const handleToggle = (): void => {
    if (hasChildren) setExpanded((v) => !v)
  }

  const handleSelect = (): void => {
    onSelect?.(node)
    if (hasChildren && !expanded) setExpanded(true)
  }

  return (
    <div>
      <div
        role="button"
        tabIndex={0}
        onClick={handleSelect}
        onKeyDown={(e) => {
          if (e.key === "Enter" || e.key === " ") {
            e.preventDefault()
            handleSelect()
          }
        }}
        className={cn(
          "flex cursor-pointer items-center gap-1 rounded-md px-2 py-1.5 text-sm transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
          isSelected && "bg-accent font-medium text-accent-foreground"
        )}
        style={{ paddingLeft: `${depth * 12 + 8}px` }}
      >
        {hasChildren ? (
          <button
            type="button"
            onClick={(e) => {
              e.stopPropagation()
              handleToggle()
            }}
            className="flex h-4 w-4 shrink-0 items-center justify-center text-muted-foreground transition-transform"
            aria-label={expanded ? "collapse" : "expand"}
          >
            {expanded ? (
              <ChevronDown className="h-3.5 w-3.5" />
            ) : (
              <ChevronRight className="h-3.5 w-3.5" />
            )}
          </button>
        ) : (
          <span className="h-4 w-4 shrink-0" />
        )}
        <Icon className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
        <span className="truncate">{node.name}</span>
      </div>
      {hasChildren && expanded && (
        <div>
          {children.map((child) =>
            matchesSearch(child, search) ? (
              <OrgTreeItem
                key={child.id}
                node={child}
                depth={depth + 1}
                onSelect={onSelect}
                selectedId={selectedId}
                search={search}
              />
            ) : null
          )}
        </div>
      )}
    </div>
  )
}

export function OrgTreeNav({ nodes, onSelect, selectedId }: OrgTreeNavProps): JSX.Element {
  const t = useTranslations("school")
  const [search, setSearch] = useState<string>("")

  const filtered = useMemo(
    () => nodes.filter((node) => matchesSearch(node, search.toLowerCase())),
    [nodes, search]
  )

  return (
    <div className="space-y-2">
      <Input
        value={search}
        onChange={(e) => setSearch(e.target.value)}
        placeholder={t("orgTree.search")}
        className="h-8 text-sm"
      />
      {filtered.length === 0 ? (
        <p className="px-2 py-4 text-center text-sm text-muted-foreground">{t("orgTree.empty")}</p>
      ) : (
        <div className="space-y-0.5">
          {filtered.map((node) => (
            <OrgTreeItem
              key={node.id}
              node={node}
              depth={0}
              onSelect={onSelect}
              selectedId={selectedId}
              search={search.toLowerCase()}
            />
          ))}
        </div>
      )}
    </div>
  )
}
