import { useCallback, useMemo, useState } from 'react';
import { AppShell } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { BrandMark, logout } from '@ema-platform/auth';
import { AppHeader, AppSidebar } from '@ema-platform/ui';
import type { NavItem, NavSection } from '@ema-platform/ui';
import { notify } from '@ema-platform/ui';
import { AppTopNav, filterByPermissions } from '@ema-platform/ui';
import { baseApi, useGetQueueCountsQuery } from '@ema-platform/api';
import { usePermissions } from '@ema-platform/auth';
import { SUPPORTED_LANGUAGES } from '../i18n/config';
import { useAppDispatch, useAppSelector } from '../store/hooks';
import { NAV_SECTIONS } from './nav-config';
import { CommandPalette } from './CommandPalette';

/**
 * How often the pending-work badges refresh.
 *
 * Polled on a timer rather than refetched per navigation: the counts sit in
 * the chrome and are visible on every screen, so tying them to route changes
 * would fire a request each time an officer clicked anything.
 */
const BADGE_POLL_MS = 60_000;

const HEADER_HEIGHT = 116;

export function BackofficeLayout() {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const location = useLocation();
  const dispatch = useAppDispatch();
  const [opened, { toggle: toggleNav }] = useDisclosure();
  const [collapsed, setCollapsed] = useState(false);
  const user = useAppSelector((state) => state.auth.user);
  const layoutMode = useAppSelector((state) => state.preferences.layoutMode);
  const { permissions: granted, known } = usePermissions();

  // TEMPORARY diagnostic — remove once the sidebar is confirmed working.
  // eslint-disable-next-line no-console
  console.log(
    '[NAV] known=', known,
    'granted=', granted.length,
    '| cookies:', document.cookie.split('; ').map((c) => c.split('=')[0]).filter((n) => n.includes('token')),
    '| token tail:', (document.cookie.match(/ema-backoffice-auth-token=([^;]+)/)?.[1] ?? 'NONE').slice(-12),
  );

  // Badges reflect real pending work. One grouped request on a timer, shared
  // by the sidebar and the top bar via the RTK cache.
  const { data: counts } = useGetQueueCountsQuery(undefined, {
    pollingInterval: BADGE_POLL_MS,
    refetchOnMountOrArgChange: false,
  });

  const sections = useMemo<NavSection[]>(() => {
    const withBadges = NAV_SECTIONS.map((section) => ({
      ...section,
      items: section.items.map((item) =>
        item.to === '/licence-review' && counts?.unassigned
          ? { ...item, badge: counts.unassigned }
          : item,
      ),
    }));
    // Unfiltered until the grant list has loaded, matching PortalLayout and
    // RequirePermission: a moment of extra nav beats a flash of empty nav.
    return known ? filterByPermissions(withBadges, granted) : withBadges;
  }, [counts?.unassigned, granted, known]);

  /** Flat list used for breadcrumbs and active-route lookup. */
  const navItems = useMemo<NavItem[]>(
    () =>
      sections.flatMap((section) =>
        section.items.flatMap((item) => [item, ...(item.children ?? [])]),
      ),
    [sections],
  );

  const displayName = user?.name?.en || user?.username || '';
  const initials = displayName
    ? displayName
        .split(/\s+/)
        .map((s) => s[0])
        .join("")
        .toUpperCase()
        .slice(0, 2)
    : "?";

  const handleLogout = useCallback(() => {
    dispatch(logout());
    dispatch(baseApi.util.resetApiState());
    navigate("/");
  }, [dispatch, navigate]);

  const segments = location.pathname.split('/').filter(Boolean);
  // Label each crumb from the nav item it corresponds to, falling back to a
  // readable form of the path segment. Every crumb was previously labelled
  // "Dashboard", which made the trail useless.
  const crumbs = [
    { label: t("nav.dashboard"), path: "/dashboard" },
    ...segments
      .map((_, i) => '/' + segments.slice(0, i + 1).join('/'))
      .filter((path) => path !== '/dashboard')
      .filter((path) => !path.startsWith('/um'))
      .map((path) => {
        const match = navItems.find((item) => item.to === path);
        if (match) return { label: t(match.label), path };
        const segment = path.split('/').pop() ?? '';
        // Ids get a generic label rather than a raw uuid in the trail.
        const isId = /^[0-9a-f-]{8,}$/i.test(segment) || /^\d+$/.test(segment);
        return {
          label: isId
            ? t('nav.details', 'Details')
            : segment.replace(/-/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()),
          path,
        };
      }),
  ];

  const go = (item: NavItem) => {
    if (item.soon) {
      notify.info(`${t(item.label)} — coming soon.`);
      return;
    }
    if (item.to) {
      navigate(item.to);
    }
  };

  const handleToggleCollapse = useCallback(() => {
    setCollapsed((prev) => !prev);
  }, []);

  const isSidebar = layoutMode === "sidebar";

  return (
    <AppShell
      header={{ height: isSidebar ? 74 : HEADER_HEIGHT }}
      navbar={
        isSidebar
          ? {
              width: collapsed ? 72 : 264,
              breakpoint: "sm",
              collapsed: { mobile: !opened },
            }
          : undefined
      }
      padding="lg"
    >
      <AppShell.Header
        style={{
          background: "var(--mantine-color-body)",
          borderBottom: "1px solid var(--mantine-color-gray-2)",
          display: "flex",
          flexDirection: "column",
        }}
      >
        <div style={{ height: 74, flexShrink: 0, padding: "0 32px" }}>
          <AppHeader
            onToggleNav={toggleNav}
            onToggleSidebar={isSidebar ? handleToggleCollapse : toggleNav}
            navOpened={opened}
            breadcrumbs={crumbs}
            onNavigate={navigate}
            onLogout={handleLogout}
            userName={displayName || t("app.name")}
            userInitials={initials}
            supportedLanguages={SUPPORTED_LANGUAGES}
          />
        </div>

        {!isSidebar && (
          <div
            style={{
              display: 'flex',
              alignItems: 'center',
              padding: '0 32px',
              height: 42,
              borderTop: '1px solid var(--mantine-color-gray-1)',
              flexShrink: 0,
            }}
          >
            {/* Grouped dropdowns. Previously every destination rendered as a
                sibling button in one horizontally scrolling row. */}
            <AppTopNav
              navItems={sections}
              activePath={location.pathname}
              onNavigate={go}
            />
          </div>
        )}
      </AppShell.Header>

      {isSidebar && (
        <AppShell.Navbar
          p={0}
          style={{
            overflow: "hidden",
            transition: "width 200ms ease",
            background: "var(--mantine-color-body)",
            borderRight: "1px solid var(--mantine-color-gray-2)",
          }}
        >
          <AppSidebar
            navItems={sections}
            collapsed={collapsed}
            activePath={location.pathname}
            onToggleCollapse={handleToggleCollapse}
            onNavigate={go}
            brandName={t('app.name')}
            brandSubtitle={t('app.authority')}
            brandLogo={<BrandMark size={32} />}
          />
        </AppShell.Navbar>
      )}

      <AppShell.Main>
        <div key={location.pathname} className="ema-page-enter">
          <Outlet />
        </div>
      </AppShell.Main>

      {/* Registered once for the whole backoffice; opens on ⌘K anywhere. */}
      <CommandPalette sections={sections} />
    </AppShell>
  );
}
