// frontend\src\components\Sidebar.tsx

import {
  Dialog,
  DialogBackdrop,
  DialogPanel,
  TransitionChild,
} from '@headlessui/react'
import {
  CalendarIcon,
  ChartPieIcon,
  ChatBubbleLeftRightIcon,
  Cog6ToothIcon,
  ComputerDesktopIcon,
  CpuChipIcon,
  DocumentDuplicateIcon,
  ServerStackIcon,
  ShieldCheckIcon,
  VideoCameraIcon,
  HomeIcon,
  XMarkIcon,
} from '@heroicons/react/24/outline'
import type { ComponentType, SVGProps } from 'react'
import { NavLink, useLocation } from 'react-router'
import { hasRight } from './permissions'
import type { User, Team } from './types'

type NavigationItem = {
  name: string
  href: string
  icon: ComponentType<SVGProps<SVGSVGElement>>
  right?: string
  children?: NavigationItem[]
}

type NavigationSection = {
  name?: string
  items: NavigationItem[]
}

const navigationSections: NavigationSection[] = [
  {
    items: [
      {
        name: 'Dashboard',
        href: '/',
        icon: HomeIcon,
      },
    ],
  },
  {
    name: 'Betrieb',
    items: [
      {
        name: 'Geräte',
        href: '/geraete',
        icon: ComputerDesktopIcon,
        right: 'devices:read',
      },
      {
        name: 'Einsätze',
        href: '/einsaetze',
        icon: VideoCameraIcon,
        right: 'operations:read',
        children: [
          {
            name: 'Milestone-Speicher',
            href: '/einsaetze/milestone-speicher',
            icon: ServerStackIcon,
            right: 'administration:read',
          },
          {
            name: 'Milestone-Geräte',
            href: '/einsaetze/milestone-devices',
            icon: CpuChipIcon,
            right: 'administration:read',
          },
        ],
      },
    ],
  },
  {
    name: 'Organisation',
    items: [
      {
        name: 'Kalender',
        href: '/kalender',
        icon: CalendarIcon,
        right: 'calendar:read',
      },
      {
        name: 'Dokumente',
        href: '/dokumente',
        icon: DocumentDuplicateIcon,
        right: 'documents:read',
      },
      {
        name: 'Berichte',
        href: '/berichte',
        icon: ChartPieIcon,
        right: 'reports:read',
      },
    ],
  },
]

type SidebarProps = {
  user: User
  sidebarOpen: boolean
  setSidebarOpen: (open: boolean) => void
  onNavigate?: () => void
}

function classNames(...classes: Array<string | false | null | undefined>) {
  return classes.filter(Boolean).join(' ')
}

function getTeamInitial(team: Team) {
  if (team.initial) {
    return team.initial
  }

  return team.name.charAt(0).toUpperCase()
}

function isPathActive(pathname: string, href: string) {
  if (href === '/') {
    return pathname === '/'
  }

  return pathname === href || pathname.startsWith(`${href}/`)
}

function itemIsActive(item: NavigationItem, pathname: string): boolean {
  return (
    isPathActive(pathname, item.href) ||
    (item.children ?? []).some((child) => itemIsActive(child, pathname))
  )
}

function filterNavigationItems(
  items: NavigationItem[],
  user: User,
): NavigationItem[] {
  return items
    .map((item) => ({
      ...item,
      children: item.children
        ? filterNavigationItems(item.children, user)
        : undefined,
    }))
    .filter((item) => {
      const canSeeItem = !item.right || hasRight(user, item.right)
      const hasVisibleChildren = Boolean(item.children?.length)

      return canSeeItem || hasVisibleChildren
    })
}

function getVisibleNavigationSections(user: User) {
  return navigationSections
    .map((section) => ({
      ...section,
      items: filterNavigationItems(section.items, user),
    }))
    .filter((section) => section.items.length > 0)
}

function SidebarContent({
  user,
  setSidebarOpen,
  onNavigate,
}: {
  user: User
  setSidebarOpen: (open: boolean) => void
  onNavigate?: () => void
}) {
  const teams = user.teams ?? []
  const location = useLocation()

  const visibleNavigationSections = getVisibleNavigationSections(user)

  const isAdministrationActive =
    location.pathname === '/administration' ||
    location.pathname.startsWith('/administration/')

  const isSettingsActive =
    location.pathname === '/einstellungen' ||
    location.pathname.startsWith('/einstellungen/')

  const isFeedbackActive = location.pathname === '/feedback'

  function handleNavigate() {
    onNavigate?.()
    setSidebarOpen(false)
  }

  function renderNavigationItem(item: NavigationItem) {
    const active = itemIsActive(item, location.pathname)
    const children = item.children ?? []
    const showChildren = children.length > 0

    return (
      <li key={item.name}>
        <NavLink
          to={item.href}
          onClick={handleNavigate}
          className={classNames(
            active
              ? 'bg-white/10 text-white shadow-sm ring-1 ring-white/10'
              : 'text-slate-400 hover:bg-white/5 hover:text-white',
            'group flex items-center gap-x-3 rounded-xl px-3 py-2.5 text-sm/6 font-semibold transition',
          )}
        >
          <item.icon
            aria-hidden="true"
            className={classNames(
              active
                ? 'text-white'
                : 'text-slate-400 group-hover:text-white',
              'size-5 shrink-0 transition',
            )}
          />
          <span className="truncate">{item.name}</span>
        </NavLink>

        {showChildren && (
          <ul
            role="list"
            className="ml-[1.35rem] mt-1 space-y-1 border-l border-white/10 pl-3"
          >
            {children.map((child) => {
              const childActive = itemIsActive(child, location.pathname)

              return (
                <li key={child.name}>
                  <NavLink
                    to={child.href}
                    onClick={handleNavigate}
                    className={classNames(
                      childActive
                        ? 'bg-indigo-500/10 text-indigo-200 ring-1 ring-indigo-400/20'
                        : 'text-slate-400 hover:bg-white/5 hover:text-white',
                      'group flex items-center gap-x-2 rounded-lg px-2.5 py-2 text-sm/6 font-medium transition',
                    )}
                  >
                    <child.icon
                      aria-hidden="true"
                      className={classNames(
                        childActive
                          ? 'text-indigo-200'
                          : 'text-slate-500 group-hover:text-white',
                        'size-4 shrink-0 transition',
                      )}
                    />
                    <span className="truncate">{child.name}</span>
                  </NavLink>
                </li>
              )
            })}
          </ul>
        )}
      </li>
    )
  }

  return (
    <>
      <div className="flex h-16 shrink-0 items-center gap-3">
        <img
          alt="Your Company"
          src="https://tailwindcss.com/plus-assets/img/logos/mark.svg?color=indigo&shade=500"
          className="h-8 w-auto"
        />
        <div className="min-w-0">
          <p className="truncate text-sm font-semibold text-white">TEG</p>
          <p className="truncate text-xs text-slate-400">SE Düsseldorf</p>
        </div>
      </div>

      <nav className="flex flex-1 flex-col">
        <ul role="list" className="flex flex-1 flex-col gap-y-6">
          <li>
            <div className="space-y-6">
              {visibleNavigationSections.map((section, sectionIndex) => (
                <section key={section.name ?? `section-${sectionIndex}`}>
                  {section.name && (
                    <h2 className="mb-2 px-3 text-[0.6875rem]/6 font-semibold uppercase tracking-wider text-slate-500">
                      {section.name}
                    </h2>
                  )}

                  <ul role="list" className="space-y-1">
                    {section.items.map(renderNavigationItem)}
                  </ul>
                </section>
              ))}
            </div>
          </li>

          <li>
            <div className="border-t border-white/10 pt-5">
              <h2 className="px-3 text-[0.6875rem]/6 font-semibold uppercase tracking-wider text-slate-500">
                Teams
              </h2>

              <ul role="list" className="mt-2 space-y-1">
                {teams.length > 0 ? (
                  teams.map((team) => (
                    <li key={team.id}>
                      <a
                        href={team.href || '#'}
                        onClick={handleNavigate}
                        className={classNames(
                          team.current
                            ? 'bg-white/10 text-white ring-1 ring-white/10'
                            : 'text-slate-400 hover:bg-white/5 hover:text-white',
                          'group flex items-center gap-x-3 rounded-xl px-3 py-2 text-sm/6 font-semibold transition',
                        )}
                      >
                        <span className="flex size-6 shrink-0 items-center justify-center rounded-lg border border-white/10 bg-white/5 text-[0.625rem] font-medium text-slate-300 group-hover:border-white/20 group-hover:text-white">
                          {getTeamInitial(team)}
                        </span>
                        <span className="truncate">{team.name}</span>
                      </a>
                    </li>
                  ))
                ) : (
                  <li className="px-3 py-1 text-sm/6 text-slate-500">
                    Keine Teams zugeordnet
                  </li>
                )}
              </ul>
            </div>
          </li>

          <li className="mt-auto border-t border-white/10 pt-5">
            <h2 className="mb-2 px-3 text-[0.6875rem]/6 font-semibold uppercase tracking-wider text-slate-500">
              Hilfe & System
            </h2>

            <ul role="list" className="space-y-1">
              <li>
                <NavLink
                  to="/feedback"
                  onClick={handleNavigate}
                  className={classNames(
                    isFeedbackActive
                      ? 'bg-white/10 text-white ring-1 ring-white/10'
                      : 'text-slate-400 hover:bg-white/5 hover:text-white',
                    'group flex items-center gap-x-3 rounded-xl px-3 py-2.5 text-sm/6 font-semibold transition',
                  )}
                >
                  <ChatBubbleLeftRightIcon
                    aria-hidden="true"
                    className="size-5 shrink-0"
                  />
                  Feedback
                </NavLink>
              </li>

              {hasRight(user, 'settings:read') && (
                <li>
                  <NavLink
                    to="/einstellungen/konto"
                    onClick={handleNavigate}
                    className={classNames(
                      isSettingsActive
                        ? 'bg-white/10 text-white ring-1 ring-white/10'
                        : 'text-slate-400 hover:bg-white/5 hover:text-white',
                      'group flex items-center gap-x-3 rounded-xl px-3 py-2.5 text-sm/6 font-semibold transition',
                    )}
                  >
                    <Cog6ToothIcon
                      aria-hidden="true"
                      className="size-5 shrink-0"
                    />
                    Einstellungen
                  </NavLink>
                </li>
              )}

              {hasRight(user, 'administration:read') && (
                <li>
                  <NavLink
                    to="/administration/benutzer"
                    onClick={handleNavigate}
                    className={classNames(
                      isAdministrationActive
                        ? 'bg-white/10 text-white ring-1 ring-white/10'
                        : 'text-slate-400 hover:bg-white/5 hover:text-white',
                      'group flex items-center gap-x-3 rounded-xl px-3 py-2.5 text-sm/6 font-semibold transition',
                    )}
                  >
                    <ShieldCheckIcon
                      aria-hidden="true"
                      className="size-5 shrink-0"
                    />
                    Administration
                  </NavLink>
                </li>
              )}
            </ul>
          </li>
        </ul>
      </nav>
    </>
  )
}

export default function Sidebar({
  user,
  sidebarOpen,
  setSidebarOpen,
  onNavigate,
}: SidebarProps) {
  return (
    <>
      <Dialog
        open={sidebarOpen}
        onClose={setSidebarOpen}
        className="relative z-[2000] lg:hidden"
      >
        <DialogBackdrop
          transition
          className="fixed inset-0 bg-gray-950/85 transition-opacity duration-300 ease-linear data-closed:opacity-0"
        />

        <div className="fixed inset-0 flex">
          <DialogPanel
            transition
            className="relative mr-16 flex w-full max-w-xs flex-1 transform transition duration-300 ease-in-out data-closed:-translate-x-full"
          >
            <TransitionChild>
              <div className="absolute top-0 left-full flex w-16 justify-center pt-5 duration-300 ease-in-out data-closed:opacity-0">
                <button
                  type="button"
                  onClick={() => setSidebarOpen(false)}
                  className="-m-2.5 p-2.5"
                >
                  <span className="sr-only">Close sidebar</span>
                  <XMarkIcon aria-hidden="true" className="size-6 text-white" />
                </button>
              </div>
            </TransitionChild>

            <div className="relative flex grow flex-col gap-y-5 overflow-y-auto bg-slate-950 px-5 pb-4 ring-1 ring-white/10 before:pointer-events-none before:absolute before:inset-0 before:bg-[radial-gradient(circle_at_top_left,rgba(99,102,241,0.16),transparent_32rem)]">
              <SidebarContent
                user={user}
                setSidebarOpen={setSidebarOpen}
                onNavigate={onNavigate}
              />
            </div>
          </DialogPanel>
        </div>
      </Dialog>

      <div className="hidden bg-slate-950 ring-1 ring-white/10 lg:fixed lg:inset-y-0 lg:z-[2000] lg:flex lg:w-72 lg:flex-col">
        <div className="relative flex grow flex-col gap-y-5 overflow-y-auto px-5 pb-4 before:pointer-events-none before:absolute before:inset-0 before:bg-[radial-gradient(circle_at_top_left,rgba(99,102,241,0.14),transparent_34rem)]">
          <SidebarContent
            user={user}
            setSidebarOpen={setSidebarOpen}
            onNavigate={onNavigate}
          />
        </div>
      </div>
    </>
  )
}
