/**
 * Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
 */
import {useEffect, useRef, useState} from 'react';
import {useDispatch, useSelector} from 'react-redux';
import moment from 'moment';

import LoggerFactory from 'services/logger/LoggerFactory';
import {channelListErrorMessages, channelListPublishingStateErrorMessages} from 'constants/index';
import {transformToPortalError} from 'utility/error-handler';
import {ITableSortSearch} from 'interfaces/tableProps';

import {IAppStore} from 'store';
import {channelsSelector, listChannels} from 'store/action/channels';
import {fetchChannelsPublishingState} from 'store/action/channels-publishing';
import {StoreScreensType} from 'store/reducers/screens';
import {screensSelector, setScreenProps} from 'store/action/screens';

import Loader from 'components/loaders';
import RequireAuthentication from 'components/requiresAuth';
import {Body, Main} from 'components/layout';
import {TableHeaderKey, ITableWithPaginationHeader} from 'components/table';
import {TableWithPagination} from 'components/table-with-pagination';

import {Error} from 'components/error-renderer/style';
import {columns} from './columns-config';
import {CreateChannelModal} from './create-channel';

const intervalFetchChannelsPublishingState = moment.duration(5, 'seconds').asMilliseconds();

export const ChannelsContainer = (): JSX.Element => {
  const logger = LoggerFactory.getLogger('views/channels/ChannelsContainer');
  const dispatch = useDispatch();
  const interval = useRef(null);
  const {channelList = [], isFetching, error} = useSelector((state: IAppStore) => channelsSelector(state));
  const {searchValue, sortDirection, sortColumn} = useSelector((state: IAppStore) => screensSelector(state)[StoreScreensType.Channels]);
  const [isCreateChannelModalOpened, setCreateChannelModalOpened] = useState(false);
  const [channels, setChannels] = useState([]);
  const [channelsIdOnDisplay, setChannelsIdOnDisplay] = useState([]);
  const channelsColumns = {...columns};
  const getChannelList = async (): Promise<void> => {
    try {
      logger.info('Fetching the list of channels');

      await dispatch(listChannels());

      logger.info('List of channels was fetched successfully');
    } catch (e) {
      const {status, message, requestPayload} = transformToPortalError(e);

      logger.error(`${channelListErrorMessages[status] || message} [%s]`, status, requestPayload);
    }
  };

  const getChannelsPublishingState = async (): Promise<void> => {
    if (isFetching || !channelsIdOnDisplay?.length) {
      return;
    }

    logger.info('Checking channels publishing state');

    try {
      await dispatch(fetchChannelsPublishingState(channelsIdOnDisplay));
    } catch (e) {
      const {status, message, requestPayload} = transformToPortalError(e);

      return logger.error(
        `${channelListPublishingStateErrorMessages[status] || message || channelListPublishingStateErrorMessages['default']} [%s]`,
        status,
        requestPayload
      );
    }
  };

  useEffect(() => {
    getChannelList();
  }, []);

  useEffect(() => {
    const modifiedChannels = channelList.map(channel => ({
      ...channel,
      extraPath: `${encodeURIComponent(channel.channelId)}/preview`
    }));

    setChannels(modifiedChannels || []);
  }, [channelList]);

  useEffect(() => {
    clearInterval(interval.current);
    interval.current = setInterval(getChannelsPublishingState, intervalFetchChannelsPublishingState);

    return () => clearInterval(interval.current);
  }, [channelsIdOnDisplay, isFetching]);

  const screenHeader: ITableWithPaginationHeader = {
    [TableHeaderKey.Search]: {},
    [TableHeaderKey.AddRow]: {
      openAddRowModal: () => {
        setCreateChannelModalOpened(true);
      }
    }
  };
  const getCurrentDisplayList = (data: Record<string, string | number | null>[]) => {
    const newChannelsIdOnDisplay: string[] = data.map(val => val?.channelId) as string[];

    setChannelsIdOnDisplay(newChannelsIdOnDisplay);
  };

  const changeScreenProps = (data: Partial<ITableSortSearch>) =>
    dispatch(
      setScreenProps({
        screen: StoreScreensType.Channels,
        data
      })
    );

  if (error) {
    return <Error>{channelListErrorMessages[error.status] || error.message}</Error>;
  }

  return (
    <>
      <Body className="table-container">
        {isFetching ? (
          <Main>
            <Loader />
          </Main>
        ) : (
          <TableWithPagination
            title={'Channels'}
            screenHeader={screenHeader}
            columns={channelsColumns}
            data={channels}
            sortColumn={sortColumn}
            sortDirection={sortDirection}
            paginationItemText={'channels'}
            getCurrentDisplayList={getCurrentDisplayList}
            changeSortProps={changeScreenProps}
            searchValue={searchValue}
            changeSearch={changeScreenProps}
          />
        )}
      </Body>
      {isCreateChannelModalOpened && <CreateChannelModal getChannelList={getChannelList} setCreateChannelModalOpened={setCreateChannelModalOpened} />}
    </>
  );
};

export default RequireAuthentication(ChannelsContainer);
