import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import { LogOut, Monitor, Moon, Sun } from 'lucide-react';
import { useState, type ReactNode } from 'react';
import { Navigate, NavLink, useNavigate } from 'react-router-dom';
import { getToken } from '@/api/client';
import { useDemoAccounts, useDemoLogin, useLogout, useMe } from '@/auth/use-auth';
import { Avatar, initialsOf } from '@/components/avatar';
import { Logo } from '@/components/logo';
import { RechercheGlobale } from '@/components/recherche-globale';
import { useQuery } from '@tanstack/react-query';
import type { ObjectCategory, PermissionRight } from '@siop/shared';
import { api } from '@/api/client';
import { usePermissions } from '@/auth/use-permissions';
import {
  IcoAscenseurs,
  IcoAssistant,
  IcoCategories,
  IcoDemandes,
  IcoFichiers,
  IcoOrdresDeTravail,
  IcoPersonnes,
  IcoPreventif,
  IcoSites,
  IcoStatistiques,
  IcoStock,
  IcoTableauDeBord,
  IcoTiers,
} from '@/components/nav-icons';
import {
  applyThemeMode,
  getThemeMode,
  nextThemeMode,
  THEME_LABELS,
  type ThemeMode,
} from '@/theme/theme';

/** Navigation de la maquette validée. Les écrans à venir restent visibles
 *  (périmètre annoncé) mais inertes, marqués de leur release ; les écrans
 *  livrés sont filtrés par la matrice (canView). */
interface LienNav {
  libelle: string;
  icone: () => ReactNode;
  route?: string;
  release?: string;
  permission?: [ObjectCategory, PermissionRight];
  badge?: 'urgences' | 'demandes';
}

const NAVIGATION: { groupe: string; liens: LienNav[] }[] = [
  {
    groupe: 'Exploitation',
    liens: [
      { libelle: 'Tableau de bord', icone: IcoTableauDeBord, route: '/' },
      { libelle: 'Ordres de travail', icone: IcoOrdresDeTravail, route: '/ot', permission: ['WORK_ORDERS', 'view'], badge: 'urgences' },
      { libelle: 'Demandes', icone: IcoDemandes, route: '/demandes', permission: ['REQUESTS', 'view'], badge: 'demandes' },
      { libelle: 'Préventif', icone: IcoPreventif, route: '/preventif', permission: ['WORK_ORDERS', 'view'] },
    ],
  },
  {
    groupe: 'Parc',
    liens: [
      { libelle: 'Ascenseurs', icone: IcoAscenseurs, route: '/ascenseurs', permission: ['ASSETS', 'view'] },
      { libelle: 'Sites', icone: IcoSites, route: '/sites', permission: ['LOCATIONS', 'view'] },
      { libelle: 'Catégories', icone: IcoCategories, route: '/categories', permission: ['SETTINGS', 'view'] },
    ],
  },
  {
    groupe: 'Ressources',
    liens: [
      { libelle: 'Stock & achats', icone: IcoStock, route: '/stock', permission: ['PARTS', 'view'] },
      { libelle: 'Tiers', icone: IcoTiers, route: '/tiers', permission: ['PURCHASE_ORDERS', 'view'] },
      { libelle: 'Fichiers', icone: IcoFichiers, route: '/bibliotheque', permission: ['ASSETS', 'view'] },
    ],
  },
  {
    groupe: 'Pilotage',
    liens: [
      { libelle: 'Statistiques', icone: IcoStatistiques, route: '/statistiques', permission: ['ANALYTICS', 'view'] },
      { libelle: 'Assistant', icone: IcoAssistant, route: '/assistant', permission: ['WORK_ORDERS', 'view'] },
      { libelle: 'Personnes', icone: IcoPersonnes, route: '/personnes', permission: ['PEOPLE_TEAMS', 'view'] },
    ],
  },
];

const THEME_ICONS: Record<ThemeMode, typeof Sun> = {
  auto: Monitor,
  light: Sun,
  dark: Moon,
};

/** L'urgence « personne bloquée » et la file de demandes — visibles partout
 *  dans la coquille (chip topbar + badges), selon les droits du rôle. */
function useSignauxExploitation(peutVoirOT: boolean, peutVoirDemandes: boolean) {
  const { data: workOrders } = useQuery({
    queryKey: ['work-orders'],
    enabled: peutVoirOT,
    refetchInterval: 60_000,
    queryFn: async () => (await api.GET('/work-orders')).data?.workOrders ?? [],
  });
  const { data: requests } = useQuery({
    queryKey: ['requests'],
    enabled: peutVoirDemandes,
    refetchInterval: 60_000,
    queryFn: async () => (await api.GET('/requests')).data?.requests ?? [],
  });
  return {
    urgences: (workOrders ?? []).filter(
      (w) => w.priority === 'PERSON_TRAPPED' && w.status !== 'DONE' && w.status !== 'CANCELLED',
    ),
    demandesATraiter: (requests ?? []).filter((r) => r.status === 'RECEIVED').length,
  };
}

export function Coquille({ children }: { children: ReactNode }) {
  const navigate = useNavigate();
  const { data: me } = useMe();
  const { data: demoAccounts } = useDemoAccounts();
  const demoLogin = useDemoLogin();
  const logout = useLogout();
  const { can } = usePermissions();
  const [themeMode, setThemeMode] = useState<ThemeMode>(getThemeMode);
  const { urgences, demandesATraiter } = useSignauxExploitation(
    can('WORK_ORDERS', 'view'),
    can('REQUESTS', 'view'),
  );

  if (!getToken()) return <Navigate to="/connexion" replace />;

  const badges: Record<'urgences' | 'demandes', number> = {
    urgences: urgences.length,
    demandes: demandesATraiter,
  };

  const cyclerTheme = () => {
    const mode = nextThemeMode(themeMode);
    applyThemeMode(mode);
    setThemeMode(mode);
  };

  const basculerDemo = (userId: string) => {
    if (userId === me?.id) return;
    demoLogin.mutate(userId, { onSuccess: () => navigate('/', { replace: true }) });
  };

  const IconeTheme = THEME_ICONS[themeMode];

  return (
    <div className="app">
      <aside className="nav">
        <Logo />
        {NAVIGATION.map(({ groupe, liens }) => (
          <nav key={groupe} aria-label={groupe}>
            <div className="groupe">{groupe}</div>
            {liens
              .filter(({ permission }) => !permission || can(...permission))
              .map(({ libelle, icone: Icone, route, release, badge }) =>
              route ? (
                <NavLink
                  key={libelle}
                  to={route}
                  end={route === '/'}
                  className={({ isActive }) => (isActive ? 'actif' : undefined)}
                >
                  <Icone />
                  {libelle}
                  {badge && badges[badge] > 0 ? (
                    <span className="badge-nav num">{badges[badge]}</span>
                  ) : null}
                </NavLink>
              ) : (
                <a
                  key={libelle}
                  href="#"
                  aria-disabled="true"
                  title={`Disponible en ${release}`}
                  onClick={(e) => e.preventDefault()}
                >
                  <Icone />
                  {libelle}
                  <span className="badge-release">{release}</span>
                </a>
              ),
            )}
          </nav>
        ))}
      </aside>

      <div className="contenu">
        <header className="topbar">
          <RechercheGlobale />
          {urgences.length > 0 ? (
            <button
              type="button"
              className="chip-urgence"
              style={{ cursor: 'pointer' }}
              onClick={() => navigate(`/ot/${urgences[0]!.id}`)}
            >
              <span className="point-pulse" />
              {urgences.length === 1
                ? '1 personne bloquée'
                : `${urgences.length} personnes bloquées`}
            </button>
          ) : null}
          <button
            type="button"
            className="btn ghost"
            onClick={cyclerTheme}
            title={THEME_LABELS[themeMode]}
            aria-label={THEME_LABELS[themeMode]}
          >
            <IconeTheme />
          </button>

          <DropdownMenu.Root>
            <DropdownMenu.Trigger asChild>
              <button type="button" className="compte" aria-label="Compte et bascule de rôle">
                {me?.isDemo ? <span className="chip-demo">DÉMO</span> : null}
                {me ? (
                  <>
                    <Avatar
                      initials={initialsOf(me.displayName)}
                      roleName={me.role.name}
                    />
                    <span className="qui">
                      <b>{me.displayName}</b>
                      <br />
                      <small>{me.role.name} ▾</small>
                    </span>
                  </>
                ) : null}
              </button>
            </DropdownMenu.Trigger>
            <DropdownMenu.Portal>
              <DropdownMenu.Content className="menu" align="end" sideOffset={8}>
                {demoAccounts && demoAccounts.length > 0 ? (
                  <>
                    <div className="titre-menu">Changer de rôle (démo)</div>
                    {demoAccounts.map((compte) => (
                      <DropdownMenu.Item
                        key={compte.id}
                        className="item"
                        disabled={compte.id === me?.id}
                        onSelect={() => basculerDemo(compte.id)}
                      >
                        <Avatar
                          initials={compte.initials}
                          roleName={compte.roleName}
                          className="h-6 w-6 text-[10px]"
                        />
                        {compte.displayName}
                        <span className="role">{compte.roleName}</span>
                      </DropdownMenu.Item>
                    ))}
                    <div className="separateur" role="separator" />
                  </>
                ) : null}
                <DropdownMenu.Item className="item" onSelect={logout}>
                  <LogOut />
                  Se déconnecter
                </DropdownMenu.Item>
              </DropdownMenu.Content>
            </DropdownMenu.Portal>
          </DropdownMenu.Root>
        </header>

        <main className="page">{children}</main>
      </div>
    </div>
  );
}
