import { useEffect, useRef, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { MODULES } from '@/shared/constants/appData';
import { APP_ROUTE_PATHS } from '@/shared/constants/routes';
import {
  DEFAULT_CAMPUS_LABEL,
  findCampusByNameOrCode,
} from '@/shared/constants/campusDisplay';
import {
  getModuleIdByRoutePath,
  getModuleRoutePath,
} from '@/shared/constants/moduleRoutes';
import { DEFAULT_PRODUCT_ROLE } from '@/shared/constants/roles';
import type { ModuleId, UserRole } from '@/shared/types/app';
import {
  getAccessibleModuleId,
  getScopedModules,
  getScopedModuleRouteRedirectPath,
  getSidebarCampusInitial,
  getSidebarRoleLabel,
  shouldShowMobileSidebarOverlay,
  withRoleAwareModuleNames,
} from '@/business/app-shell/selectors';
import { useCampusCatalog } from '@/business/campuses/hooks';
import { useScopeContext } from '@/shared/app/scope-context';
import type {
  AppShellState,
  SidebarPage,
  SidebarProps,
  UseAppShellOptions,
} from '@/business/app-shell/types';
import type { ActiveTenant } from '@/shared/types/scope';

interface ScopeRouteState {
  readonly __scope?: ActiveTenant | null;
  readonly [key: string]: unknown;
}

function sameScopeTenant(a: ActiveTenant | null, b: ActiveTenant | null): boolean {
  if (a === b) return true;
  if (!a || !b) return a === b;
  return a.id === b.id && a.level === b.level;
}

function getUserRole(options: UseAppShellOptions): UserRole {
  return options.profile?.role ?? DEFAULT_PRODUCT_ROLE;
}

function getUserName(options: UseAppShellOptions): string {
  return options.profile?.full_name ?? '';
}

function getUserCampus(options: UseAppShellOptions): string {
  return options.profile?.campus ?? DEFAULT_CAMPUS_LABEL;
}

export function useAppShell(options: UseAppShellOptions): AppShellState {
  const location = useLocation();
  const navigate = useNavigate();
  const { tier, selectedTenant, resetScope, setScopeTenant } = useScopeContext();
  const campusCatalog = useCampusCatalog();
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
  const [zoneCheckIn, setZoneCheckIn] = useState<string | null>(null);

  const userRole = getUserRole(options);
  const userName = getUserName(options);
  const userCampus = getUserCampus(options);
  const effectiveTier = selectedTenant ? selectedTenant.level : tier;
  const isDrilled = selectedTenant !== null;
  const effectiveScopeKey = selectedTenant
    ? `${selectedTenant.level}:${selectedTenant.id}`
    : `own:${tier}`;
  const previousScopeKey = useRef(effectiveScopeKey);
  const previousPathname = useRef(location.pathname);
  const scopedModules = getScopedModules(MODULES, options.user, effectiveTier, isDrilled);
  const currentRouteModule = getModuleIdByRoutePath(location.pathname);
  const currentModule = getAccessibleModuleId(scopedModules, currentRouteModule, options.user);
  const activeModule = getAccessibleModuleId(scopedModules, currentModule, options.user);
  const campusInfo = findCampusByNameOrCode(campusCatalog.campuses, userCampus);
  const mobileOverlayVisible = shouldShowMobileSidebarOverlay(options.isMobile, mobileSidebarOpen);
  const routeState = (location.state as ScopeRouteState | null) ?? null;
  const routeScopeTenant = routeState?.__scope ?? null;

  useEffect(() => {
    const scopeChanged = previousScopeKey.current !== effectiveScopeKey;
    const pathnameChanged = previousPathname.current !== location.pathname;
    previousScopeKey.current = effectiveScopeKey;
    previousPathname.current = location.pathname;

    if (pathnameChanged && !scopeChanged && !sameScopeTenant(routeScopeTenant, selectedTenant)) {
      if (routeScopeTenant) {
        setScopeTenant(routeScopeTenant);
      } else {
        resetScope();
      }
      return;
    }

    if (location.pathname === APP_ROUTE_PATHS.platformDashboard && tier === 'global' && selectedTenant !== null) {
      if (scopeChanged) {
        const drilledRedirectPath = getScopedModuleRouteRedirectPath(
          MODULES,
          location.pathname,
          options.user,
          effectiveTier,
          isDrilled,
        );
        if (drilledRedirectPath && drilledRedirectPath !== location.pathname) {
          navigate(drilledRedirectPath, {
            replace: true,
            state: { ...routeState, __scope: selectedTenant },
          });
        }
        return;
      }
    }

    const redirectPath = getScopedModuleRouteRedirectPath(
      MODULES,
      location.pathname,
      options.user,
      effectiveTier,
      isDrilled,
    );
    if (redirectPath && redirectPath !== location.pathname) {
      navigate(redirectPath, {
        replace: true,
        state: { ...routeState, __scope: selectedTenant },
      });
      return;
    }

    if (!sameScopeTenant(routeScopeTenant, selectedTenant)) {
      navigate(
        {
          pathname: location.pathname,
          search: location.search,
          hash: location.hash,
        },
        {
          replace: true,
          state: { ...routeState, __scope: selectedTenant },
        },
      );
    }
  }, [
    effectiveScopeKey,
    location.hash,
    effectiveTier,
    isDrilled,
    location.pathname,
    location.search,
    navigate,
    options.user,
    resetScope,
    routeScopeTenant,
    routeState,
    selectedTenant,
    setScopeTenant,
    tier,
  ]);

  const setCurrentModule = (id: ModuleId) => {
    const targetModule = scopedModules.find((module) => module.id === id);
    navigate(
      targetModule?.routePath ?? scopedModules[0]?.routePath ?? getModuleRoutePath(id),
      {
        state: { ...routeState, __scope: selectedTenant },
      },
    );

    if (options.isMobile) {
      setMobileSidebarOpen(false);
    }
  };

  const toggleSidebar = () => {
    if (options.isMobile) {
      setMobileSidebarOpen((current) => !current);
      return;
    }

    setSidebarCollapsed((current) => !current);
  };

  const sidebarProps: SidebarProps = {
    currentModule: activeModule,
    setCurrentModule,
    user: options.user,
    userRole,
    collapsed: options.isMobile ? false : sidebarCollapsed,
    setCollapsed: setSidebarCollapsed,
    campusInfo,
  };

  const topBarProps = {
    user: options.user,
    userRole,
    userName,
    campusInfo,
    toggleSidebar,
    setCurrentModule,
  };

  const shellOutletContext = {
    user: options.user,
    userRole,
    userName,
    userCampus,
    zoneCheckIn,
    setZoneCheckIn,
    setCurrentModule,
  };

  const footerProps = {
    userName,
    userRole,
    modules: scopedModules,
    setCurrentModule,
  };

  return {
    activeModule,
    currentModule: activeModule,
    userRole,
    userName,
    userCampus,
    campusInfo,
    sidebarCollapsed,
    mobileSidebarOpen,
    mobileOverlayVisible,
    zoneCheckIn,
    sidebarProps,
    topBarProps,
    shellOutletContext,
    footerProps,
    setSidebarCollapsed,
    setMobileSidebarOpen,
    setZoneCheckIn,
    setCurrentModule,
  };
}

export function useSidebarPage({
  currentModule,
  setCurrentModule,
  user,
  userRole,
  collapsed,
  setCollapsed,
  campusInfo,
}: SidebarProps): SidebarPage {
  const { tier, selectedTenant } = useScopeContext();
  const effectiveTier = selectedTenant ? selectedTenant.level : tier;
  const isDrilled = selectedTenant !== null;

  return {
    currentModule,
    user,
    userRole,
    collapsed,
    campusInfo,
    modules: withRoleAwareModuleNames(
      getScopedModules(MODULES, user, effectiveTier, isDrilled),
      userRole,
    ),
    roleLabel: getSidebarRoleLabel(userRole),
    campusInitial: getSidebarCampusInitial(campusInfo),
    setCurrentModule,
    toggleCollapsed: () => setCollapsed(!collapsed),
  };
}
