import { useReducer } from 'react';
import { useInfiniteQuery } from 'react-query';
import { Link } from 'react-router-dom';

import { times } from 'lodash-es';
import { useDebounce } from '@material-hu/hooks/useDebounce';
import Stack from '@material-hu/mui/Stack';

import PxTableRowSkeleton from '@material-hu/components/composed-components/peopleExperience/TableRowSkeleton';
import Button from '@material-hu/components/design-system/Buttons/Button';
import HuChips from '@material-hu/components/design-system/Chip';
import HuSearch from '@material-hu/components/design-system/Inputs/Search';
import HuPills from '@material-hu/components/design-system/Pills';
import HuTable from '@material-hu/components/design-system/Table';
import HuTableBody from '@material-hu/components/design-system/Table/components/TableBody';
import HuTableCell from '@material-hu/components/design-system/Table/components/TableCell';
import HuTableContainer from '@material-hu/components/design-system/Table/components/TableContainer';
import HuTableHead from '@material-hu/components/design-system/Table/components/TableHead';
import HuTableLoader from '@material-hu/components/design-system/Table/components/TableLoader';
import HuTableRow from '@material-hu/components/design-system/Table/components/TableRow';
import HuTitle from '@material-hu/components/design-system/Title';

import { useAuth } from 'src/contexts/JWTContext';
import useFormatDate from 'src/hooks/useFormatDate';
import { useScopedFeature } from 'src/hooks/useScopedFeature';
import { getManagerSurveys } from '../../services';
import {
  type ManagerSurvey,
  ManagerSurveyStatus,
  type ManagerSurveysParams,
} from '../../types';
import { type LokaliseTFunction, useLokaliseTranslation } from 'src/utils/i18n';

import EmptyState from '../../components/EmptyState';
import { pxKeys } from '../../queries';
import { pxLinks, pxRoutes } from '../../routes';

const COLUMNS_LENGTH = 5;

const getFilterChipLabel = ({
  t,
  status,
}: {
  t: LokaliseTFunction;
  status: ManagerSurveyStatus | null;
}) => {
  switch (status) {
    case ManagerSurveyStatus.ACTIVE:
      return t('survey.active_other');
    case ManagerSurveyStatus.FINISHED:
      return t('survey.finished_other');
    case ManagerSurveyStatus.IMPORTED:
      return t('survey.imported_other');
    default:
      return t('survey.all');
  }
};

const getStatusPillLabel = ({
  t,
  status,
}: {
  t: LokaliseTFunction;
  status: ManagerSurveyStatus;
}) => {
  switch (status) {
    case ManagerSurveyStatus.ACTIVE:
      return t('survey.active_one');
    case ManagerSurveyStatus.FINISHED:
      return t('survey.finished_one');
    case ManagerSurveyStatus.IMPORTED:
      return t('survey.imported_one');
  }
};

const reducer = (
  currentState: ManagerSurveysParams,
  payload: Partial<ManagerSurveysParams>,
) => Object.assign({}, currentState, payload);

const initialFilters: ManagerSurveysParams = {
  q: '',
  status: undefined,
};

const STATUSES_PILL_TYPE: Record<
  ManagerSurveyStatus,
  React.ComponentProps<typeof HuPills>['type']
> = {
  [ManagerSurveyStatus.ACTIVE]: 'success',
  [ManagerSurveyStatus.FINISHED]: 'highlight',
  [ManagerSurveyStatus.IMPORTED]: 'disabled',
};

type SurveysListProps = {
  onScrollToTop: () => void;
};

const SurveysList = ({ onScrollToTop }: SurveysListProps) => {
  const { t } = useLokaliseTranslation(['people_experience', 'general']);
  const { instance } = useAuth();

  const { isEnabled: isExperimentalResultsEnabled } = useScopedFeature(
    'ENABLE_WEB_EXPERIMENTAL_RESULTS',
  );

  const [filters, setFilters] = useReducer(reducer, initialFilters);
  const { q, status } = filters;
  const debouncedSearch = useDebounce(q);
  const { formatDate } = useFormatDate();

  const hasFiltersApplied = !!(q || status);

  const reqParams: ManagerSurveysParams = {
    status,
    q: q ? debouncedSearch : q,
  };

  const { data, isLoading, fetchNextPage, isFetchingNextPage } =
    useInfiniteQuery({
      queryKey: pxKeys.managerSurveys(reqParams),
      queryFn: ({ pageParam = 1 }) =>
        getManagerSurveys({ ...reqParams, page: pageParam }),
      getNextPageParam: lastPage =>
        lastPage.data.page < lastPage.data.totalPages
          ? lastPage.data.page + 1
          : null,
    });

  const surveys = data?.pages.flatMap(page => page.data.items);

  const getViewResultsButton = (item: ManagerSurvey) => {
    if (
      ![ManagerSurveyStatus.ACTIVE, ManagerSurveyStatus.FINISHED].includes(
        item.status,
      )
    ) {
      return null;
    }

    return (
      <Button
        component={Link}
        to={
          isExperimentalResultsEnabled
            ? pxLinks.managerResultsExperimental(item.id)
            : pxRoutes.surveyManagerResults(item.id)
        }
        size="small"
      >
        {t(
          item.status === ManagerSurveyStatus.ACTIVE
            ? 'PARTIAL_RESULTS'
            : 'SEE_RESULTS',
        )}
      </Button>
    );
  };

  const handleChangeSearch = (nextValue: ManagerSurveysParams['q']) => {
    setFilters({ q: nextValue });
  };

  const handleChangeStatus = (nextValue: ManagerSurveysParams['status']) => {
    setFilters({ status: nextValue });
  };

  return (
    <>
      <Stack
        sx={{
          flexDirection: 'row',
          alignItems: 'center',
          gap: 2,
        }}
      >
        <HuSearch
          variant="classic"
          value={q ?? ''}
          onChange={handleChangeSearch}
        />
        <Stack sx={{ flexDirection: 'row', gap: 0.5 }}>
          {[null, ManagerSurveyStatus.ACTIVE, ManagerSurveyStatus.FINISHED].map(
            filter => (
              <HuChips
                key={filter}
                label={getFilterChipLabel({ t, status: filter ?? null })}
                onClick={() => handleChangeStatus(filter ?? undefined)}
                isSelected={filter === status}
              />
            ),
          )}
        </Stack>
      </Stack>
      <Stack sx={{ gap: 1 }}>
        <HuTableContainer>
          <HuTable
            sx={{
              minWidth: 650,
              tableLayout: 'fixed',
            }}
          >
            <colgroup>
              <col style={{ width: '300px' }} />
              <col />
              <col />
              <col style={{ width: '240px' }} />
              <col />
              <col style={{ width: '150px' }} />
              <col />
              <col style={{ width: '150px' }} />
              <col />
              <col style={{ width: '150px' }} />
              <col />
            </colgroup>
            <HuTableHead>
              <HuTableRow headerRow>
                <HuTableCell
                  colSpan={3}
                  headerCell
                >
                  {t('general:name')}
                </HuTableCell>
                <HuTableCell
                  colSpan={2}
                  headerCell
                >
                  {t('LAUNCH')}
                </HuTableCell>
                <HuTableCell
                  colSpan={2}
                  headerCell
                >
                  {t('ENDS')}
                </HuTableCell>
                <HuTableCell
                  colSpan={2}
                  headerCell
                >
                  {t('status')}
                </HuTableCell>
                <HuTableCell
                  colSpan={2}
                  headerCell
                ></HuTableCell>
              </HuTableRow>
            </HuTableHead>
            <HuTableBody>
              {isLoading &&
                times(8, row => (
                  <PxTableRowSkeleton
                    key={row}
                    columnsLength={COLUMNS_LENGTH}
                    getTableCellProps={column => ({
                      colSpan: column === 0 ? 3 : 2,
                    })}
                  />
                ))}
              {!isLoading && surveys?.length === 0 && (
                <HuTableRow>
                  <HuTableCell colSpan={10}>
                    <EmptyState
                      title={t(
                        hasFiltersApplied
                          ? 'empty_filtered_surveys_title'
                          : 'empty_surveys_title',
                      )}
                      description={t(
                        hasFiltersApplied
                          ? 'empty_filtered_surveys_description'
                          : 'empty_surveys_description',
                        { instanceName: instance?.name },
                      )}
                    />
                  </HuTableCell>
                </HuTableRow>
              )}
              {surveys?.map(item => (
                <HuTableRow
                  key={item.id}
                  hover
                >
                  <HuTableCell colSpan={3}>
                    <HuTitle
                      variant="S"
                      title={item.name}
                      description={item.description}
                      fontWeight="fontWeightRegular"
                      withEllipsis
                    />
                  </HuTableCell>
                  <HuTableCell colSpan={2}>
                    {item.launchDate ? formatDate(item.launchDate) : '--'}
                  </HuTableCell>
                  <HuTableCell colSpan={2}>
                    {item.finishDate ? formatDate(item.finishDate) : '--'}
                  </HuTableCell>
                  <HuTableCell colSpan={2}>
                    <HuPills
                      label={getStatusPillLabel({ t, status: item.status })}
                      size="small"
                      type={STATUSES_PILL_TYPE[item.status]}
                      hasIcon={false}
                    />
                  </HuTableCell>
                  <HuTableCell colSpan={2}>
                    {getViewResultsButton(item)}
                  </HuTableCell>
                </HuTableRow>
              ))}
              {isFetchingNextPage &&
                times(4, row => (
                  <PxTableRowSkeleton
                    key={row}
                    columnsLength={COLUMNS_LENGTH}
                    getTableCellProps={column => ({
                      colSpan: column === 0 ? 3 : 2,
                    })}
                  />
                ))}
            </HuTableBody>
          </HuTable>
        </HuTableContainer>
        {surveys && surveys.length > 0 && (
          <HuTableLoader
            loadedCount={surveys.length}
            totalCount={data?.pages[0].data.count ?? 0}
            onLoadMore={fetchNextPage}
            onScrollToTop={onScrollToTop}
          />
        )}
      </Stack>
    </>
  );
};

export default SurveysList;
