import { useCallback, useRef } from 'react';
import { Helmet } from 'react-helmet-async';
import { useQuery } from 'react-query';
import { useLocation, useNavigate, useParams } from 'react-router-dom';

import Box from '@material-hu/mui/Box';
import Stack from '@material-hu/mui/Stack';
import { type Theme, useTheme } from '@material-hu/mui/styles';
import useMediaQuery from '@material-hu/mui/useMediaQuery';

import StateCard from '@material-hu/components/composed-components/StateCard';
import HuSpinner from '@material-hu/components/design-system/ProgressIndicators/Spinner';
import HuTabs from '@material-hu/components/design-system/Tabs';

import { useAuth } from 'src/contexts/JWTContext';
import { useMobileLayout } from 'src/hooks/useMobileLayout';
import { useMobileToken } from 'src/hooks/useMobileToken';
import { getCompetition, prodeKeys } from 'src/services/prode';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import PredictionsTab from './components/PredictionsTab';
import RankingTab from './components/RankingTab';
import RulesTab from './components/RulesTab';
import SportsPoolLayout from './components/SportsPoolLayout';
import {
  detailContainerSx,
  detailContentSx,
  loadingContainerSx,
} from './constants';
import useCompetitions from './hooks/useCompetitions';
import useSportsPoolRoutes from './hooks/useSportsPoolRoutes';
import { getTabFromPath, type TabValue } from './utils';

const CompetitionDetail = () => {
  const { competitionId } = useParams<{ competitionId: string }>();
  const navigate = useNavigate();
  const location = useLocation();
  const { t } = useLokaliseTranslation('sportsPool');
  const { isAuthenticated, isInitialized } = useAuth();
  const routes = useSportsPoolRoutes();
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
  const scrollContainerRef = useRef<HTMLDivElement>(null);

  const handleResetScroll = useCallback(() => {
    scrollContainerRef.current?.scrollTo({ top: 0, behavior: 'smooth' });
  }, []);

  // Temp work around
  useMobileToken();
  useMobileLayout();

  const {
    accessData,
    isSingleCompetition,
    isLoading: isCompetitionsLoading,
  } = useCompetitions();

  const handleNavigateBack = () => navigate(routes.competitions());
  const handleNavigateToMain = () => navigate('/');

  const currentTab = getTabFromPath(location.pathname);

  const competitionIdNum = Number(competitionId);
  const isQueryEnabled = isAuthenticated && !!competitionIdNum;

  const { data: competition, isLoading: isCompetitionLoading } = useQuery(
    prodeKeys.competition(competitionIdNum),
    () => getCompetition(competitionIdNum),
    {
      enabled: isQueryEnabled,
      select: res => res.data,
    },
  );

  const isLoading = !isInitialized || isCompetitionLoading;

  const sharedLayoutSlotProps = {
    root: {
      sx: {
        backgroundColor: (theme: Theme) =>
          theme.palette.new.background.layout.default,
      },
    },
    header: {
      title: accessData?.moduleName || t('competition.page_title'),
      onBack: isSingleCompetition ? handleNavigateToMain : handleNavigateBack,
      onClose: isSingleCompetition ? handleNavigateToMain : handleNavigateBack,
      loading: isCompetitionsLoading,
    },
  };

  if (isLoading) {
    return (
      <SportsPoolLayout
        slotProps={{
          ...sharedLayoutSlotProps,
          header: { ...sharedLayoutSlotProps.header, loading: true },
        }}
      >
        <Stack sx={loadingContainerSx}>
          <HuSpinner />
        </Stack>
      </SportsPoolLayout>
    );
  }

  if (!competition) {
    return (
      <SportsPoolLayout slotProps={sharedLayoutSlotProps}>
        <Stack
          sx={{
            flex: 1,
            alignItems: 'center',
            justifyContent: 'center',
            p: 4,
          }}
        >
          <StateCard
            slotProps={{
              title: {
                title: t('competitions.no_access_title'),
                description: t('competitions.no_access_description'),
              },
            }}
          />
        </Stack>
      </SportsPoolLayout>
    );
  }

  const TAB_ROUTE_MAP: Record<TabValue, (id: number) => string> = {
    predictions: routes.competition,
    ranking: routes.ranking,
    rules: routes.rules,
  };

  const isTabValue = (v: string): v is TabValue => v in TAB_ROUTE_MAP;

  const handleTabChange = (value: string) => {
    if (!isTabValue(value)) return;
    scrollContainerRef.current?.scrollTo({ top: 0 });
    navigate(TAB_ROUTE_MAP[value](competitionIdNum), { replace: true });
  };

  const handleTabsClickCapture: React.MouseEventHandler<HTMLDivElement> = e => {
    const tabEl = (e.target as HTMLElement).closest('[role="tab"]');
    if (!tabEl) return;
    const isActive = tabEl.getAttribute('aria-selected') === 'true';
    if (isActive) {
      handleResetScroll();
    }
  };

  const tabs = [
    {
      label: t('tabs.predictions'),
      value: 'predictions',
      component: (
        <PredictionsTab
          competitionId={competitionIdNum}
          competition={competition}
          onNavigateToRanking={() => handleTabChange('ranking')}
          onResetScroll={handleResetScroll}
        />
      ),
    },
    {
      label: t('tabs.ranking'),
      value: 'ranking',
      component: <RankingTab competitionId={competitionIdNum} />,
    },
    {
      label: t('tabs.rules'),
      value: 'rules',
      component: <RulesTab competitionId={competitionIdNum} />,
    },
  ];

  const moduleName = accessData?.moduleName || t('title');
  const currentTabLabel =
    tabs.find(tab => tab.value === currentTab)?.label ?? '';
  const pageTitle = formatTitle(`${moduleName} - ${currentTabLabel}`);

  return (
    <>
      <Helmet>
        <title>{pageTitle}</title>
      </Helmet>
      <SportsPoolLayout slotProps={sharedLayoutSlotProps}>
        <Stack
          ref={scrollContainerRef}
          sx={detailContainerSx}
        >
          <Stack sx={detailContentSx}>
            <Box
              onClickCapture={handleTabsClickCapture}
              sx={theme => ({
                position: 'sticky',
                top: 0,
                zIndex: 1,
                mx: { xs: -2, md: 0 },
                px: { xs: 2, md: 0 },
                backgroundColor: {
                  xs: theme.palette.new.background.elements.default,
                  md: theme.palette.new.background.layout.default,
                },
              })}
            >
              <HuTabs
                tabs={tabs}
                value={currentTab}
                onTabChange={handleTabChange}
                variant={isMobile ? 'fullWidth' : 'standard'}
              />
            </Box>

            {tabs.find(tab => tab.value === currentTab)?.component}
          </Stack>
        </Stack>
      </SportsPoolLayout>
    </>
  );
};

export default CompetitionDetail;
