import {
  createContext,
  type ReactNode,
  useCallback,
  useContext,
  useMemo,
  useState,
} from 'react';

import { insertIf } from 'src/utils/arrays';
import { useLokaliseTranslation } from 'src/utils/i18n';

import General from './General';
import { useSubordinates } from './hooks/useSubordinates';
import MyGoals from './MyGoals';
import MyTeam from './MyTeam';

export enum TabsEnum {
  GENERAL = 'GENERAL',
  MY_TEAM = 'MY_TEAM',
  MY_GOALS = 'MY_GOALS',
}

export type GoalsContextType = {
  selectedTab: TabsEnum;
  setSelectedTab: React.Dispatch<React.SetStateAction<TabsEnum>>;
  goalsTabs: { label: string; value: TabsEnum }[];
  handleTabChange: (value: TabsEnum) => void;
  TabComponents: typeof TabComponents;
  TabsEnum: typeof TabsEnum;
  setLastVisitedTab: (tab: TabsEnum) => void;
  getLastVisitedTab: () => TabsEnum;
};

const GoalsContext = createContext<GoalsContextType | null>(null);

const TabComponents = {
  [TabsEnum.GENERAL]: General,
  [TabsEnum.MY_TEAM]: MyTeam,
  [TabsEnum.MY_GOALS]: MyGoals,
};

const LAST_TAB_KEY = 'goals_last_tab';

const validTabs = new Set([
  TabsEnum.GENERAL,
  TabsEnum.MY_GOALS,
  TabsEnum.MY_TEAM,
]);

const getSelectedTabInitialState = (): TabsEnum => {
  const lastTab = sessionStorage.getItem(LAST_TAB_KEY);
  if (validTabs.has(lastTab as TabsEnum)) {
    return lastTab as TabsEnum;
  }
  return TabsEnum.MY_GOALS;
};

export const GoalsProvider = ({ children }: { children: ReactNode }) => {
  const { t } = useLokaliseTranslation('goals');
  const [selectedTab, setSelectedTab] = useState<TabsEnum>(
    getSelectedTabInitialState,
  );

  const { hasSubordinates } = useSubordinates();

  const goalsTabs = useMemo(
    () => [
      { label: t('my_goals.title'), value: TabsEnum.MY_GOALS },
      ...insertIf(hasSubordinates, {
        label: t('my_team.title'),
        value: TabsEnum.MY_TEAM,
      }),
      { label: t('general'), value: TabsEnum.GENERAL },
    ],
    [t, hasSubordinates],
  );

  const handleTabChange = useCallback((value: TabsEnum) => {
    setSelectedTab(value);
    sessionStorage.setItem(LAST_TAB_KEY, value);
  }, []);

  const setLastVisitedTab = useCallback((tab: TabsEnum) => {
    sessionStorage.setItem(LAST_TAB_KEY, tab);
  }, []);

  const getLastVisitedTab = useCallback((): TabsEnum => {
    const lastTab = sessionStorage.getItem(LAST_TAB_KEY);
    if (validTabs.has(lastTab as TabsEnum)) {
      return lastTab as TabsEnum;
    }
    return TabsEnum.MY_GOALS;
  }, []);

  const value = useMemo(
    () => ({
      selectedTab,
      setSelectedTab,
      goalsTabs,
      handleTabChange,
      TabComponents,
      TabsEnum,
      setLastVisitedTab,
      getLastVisitedTab,
    }),
    [
      selectedTab,
      goalsTabs,
      handleTabChange,
      setLastVisitedTab,
      getLastVisitedTab,
    ],
  );

  return (
    <GoalsContext.Provider value={value}>{children}</GoalsContext.Provider>
  );
};

export const useGoalsContext = () => {
  const context = useContext(GoalsContext);
  if (!context)
    throw new Error('useGoalsContext must be used within a GoalsProvider');
  return context;
};
