import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import classNames from 'clsx';
import dayjs from 'dayjs';
import { useRouter } from 'next/router';
import {
  AddRounded,
  CodeRounded,
  ContentCopyRounded,
  DeleteRounded,
  FilterAltRounded,
  SearchRounded,
} from '@mui/icons-material';

import {
  ALL_TYPE,
  ASPECT_RATIOS,
  EMBED_CODE_TYPES,
  PLAYER_TYPES,
  SEARCH_TEXT_MAX_LENGTH,
  TABLE_HEADER,
} from '../constants';
import { PCN_DELETE_PLAYER_NEW, PCN_POST_PLAYER_NEW } from '@/modules/@common/acl/constants';
import { ASPECT_RATIO_9_16_VALUE } from '@/modules/@common/constants/aspectRatios';
import { TYPE_VERTICAL } from '@/modules/@common/constants/playerTypes';

import * as playerSelectors from '../redux/selectors';
import {
  deletePlayerAction,
  getDataAction,
  getPublishersOptionsAction,
  getUiPropsAction,
  setAction,
  setAspectRatio,
  setEmbedCodeAction,
  setEmbedCodeByTypeAction,
  setTableAction,
} from '../redux/slices';
import { hasPermission } from '@/modules/@common/user/helpers';
import { getUserPermissionsSelector } from '@/modules/@common/user/redux/selectors';
import { omitUndefinedProps } from '@/mui/helpers';

import EmbedCodePopup from '@/modules/@common/EmbedCodePopup';
import CommonList from '@/modules/@common/List';
import CommonTable, { TableCellActions } from '@/modules/@common/Table';
import Empty from './Empty/Empty';
import {
  Autocomplete,
  Button,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Divider,
  IconButton,
  InputAdornment,
  Menu,
  MenuItem,
  Select,
  Stack,
  TableCell,
  TableRow,
  TextField,
  Tooltip,
  Typography,
} from '@/mui/components';

import styles from './Players.module.scss';

function Players() {
  const router = useRouter();
  const dispatch = useDispatch();

  const data = useSelector(playerSelectors.dataSelector);

  const page = useSelector(playerSelectors.pageSelector);
  const pageSize = useSelector(playerSelectors.pageSizeSelector);
  const totalCount = useSelector(playerSelectors.totalCountSelector);
  const sortBy = useSelector(playerSelectors.sortBySelector);
  const sortOrder = useSelector(playerSelectors.sortOrderSelector);
  const search = useSelector(playerSelectors.searchSelector);

  const allRecordsCount = useSelector(playerSelectors.allRecordsCountSelector);

  const type = useSelector(playerSelectors.typeSelector);
  const typesOptions = useSelector(playerSelectors.typesOptionsSelector);
  const publisher = useSelector(playerSelectors.publisherSelector);
  const publishersOptions = useSelector(playerSelectors.publishersOptionsSelector);
  const embedCode = useSelector(playerSelectors.embedCodeSelector);
  const aspectRatio = useSelector(playerSelectors.aspectRatioSelector);
  useSelector(playerSelectors.aspectRatioSelector);
  const userPermissions = useSelector(getUserPermissionsSelector);

  const shouldShowEmpty = Array.isArray(data) && !allRecordsCount;

  const [showEmbedPopup, setShowEmbedPopup] = useState(false);
  const [showDeleteDialog, setShowDeleteDialog] = useState(false);
  const [selectedPlayerId, setSelectedPlayerId] = useState(null);
  const [selectedEmbedCodeType, setSelectedEmbedCodeType] = useState(EMBED_CODE_TYPES[0]);
  const [anchorEl, setAnchorEl] = useState(null);
  const [isDisabledEmbedCodeAspectRatio, setIsDisabledEmbedCodeAspectRatio] = useState(false);
  const [showEmbedCodeType, setShowEmbedCodeType] = useState(false);

  useEffect(() => {
    dispatch(getDataAction());
    dispatch(getUiPropsAction());
  }, []);

  const canCreatePlayer = hasPermission(PCN_POST_PLAYER_NEW, userPermissions);
  const canDeletePlayer = hasPermission(PCN_DELETE_PLAYER_NEW, userPermissions);
  const open = Boolean(anchorEl);

  const handleFilter = (filter) => {
    const { sortBy: sortBy$, sortOrder: sortOrder$, page: page$, pageSize: pageSize$, ...mainState } = filter;

    dispatch(
      setTableAction(
        omitUndefinedProps({
          sortBy: sortBy$,
          sortOrder: sortOrder$,
          page: page$,
          pageSize: pageSize$,
          selected: [],
        }),
      ),
    );

    dispatch(
      setAction({
        ...mainState,
      }),
    );
    dispatch(getDataAction());
  };

  const renderRowActions = (row) => {
    const actions = [
      {
        title: 'Embed',
        Icon: CodeRounded,
        onClick: () => {
          const verticalAspectRatioObj = ASPECT_RATIOS.find((aRatio) => aRatio.value === ASPECT_RATIO_9_16_VALUE);
          const playerType = PLAYER_TYPES.find(({ id }) => id === row.type);
          setIsDisabledEmbedCodeAspectRatio(playerType?.embedCodeAspectRatioDisabled);
          setShowEmbedCodeType(playerType?.embedCodeTypes);
          setSelectedPlayerId(row.id);
          dispatch(
            setAspectRatio({
              aspectRatioObj: row.type === TYPE_VERTICAL ? verticalAspectRatioObj : ASPECT_RATIOS[0],
              id: row.id,
            }),
          );
          dispatch(setEmbedCodeAction({ id: row.id }));
          setShowEmbedPopup(true);
        },
      },
      {
        title: 'Duplicate',
        Icon: ContentCopyRounded,
        onClick: () => router.push(`/player/${row.type}/new?copy=${row.id}`),
      },
    ];

    if (canDeletePlayer) {
      actions.push({
        title: 'Delete',
        Icon: DeleteRounded,
        onClick: () => {
          setSelectedPlayerId(row.id);
          setShowDeleteDialog(true);
        },
      });
    }
    return (
      <>
        {actions.map(({ title, Icon, onClick }) => (
          <Tooltip key={title} title={title} disableInteractive>
            <IconButton
              size="small"
              title={title}
              onClick={(event) => {
                event.stopPropagation();
                onClick();
              }}
            >
              <Icon />
            </IconButton>
          </Tooltip>
        ))}
      </>
    );
  };

  const renderTableCell = (id, row) => {
    let component;
    switch (id) {
      case 'type':
        component = PLAYER_TYPES.find(($type) => $type.id === row[id])?.name;
        break;
      case 'publisher':
        component = row[id]?.name;
        break;
      case 'updatedAt':
        component = dayjs(row[id]).format('MMM D, YYYY hh:mm A');
        break;
      case 'rowActions':
        component = renderRowActions(row);
        break;
      case 'alias':
      case 'comments':
        component = (
          <Typography variant="body2" color="text.primary" rows={1} title={row[id]}>
            {row[id]}
          </Typography>
        );
        break;
      default:
        component = row[id];
        break;
    }
    return id === 'rowActions' ? (
      <TableCellActions key={id}>{component}</TableCellActions>
    ) : (
      <TableCell key={id}>
        <div className={classNames(styles.Cell, { [styles.Cell___nowrap]: id !== 'alias' && id !== 'comments' })}>
          {component}
        </div>
      </TableCell>
    );
  };

  return (
    <CommonList
      title="Players"
      renderFilters={
        <Stack direction="row" alignItems="center" spacing={2}>
          <TextField
            className={styles.SearchField}
            size="small"
            placeholder="Search"
            value={search}
            onChange={({ target }) => handleFilter({ search: target.value, page: 1 })}
            inputProps={{
              autoComplete: 'off',
              maxLength: SEARCH_TEXT_MAX_LENGTH,
            }}
            InputProps={{
              endAdornment: (
                <InputAdornment position="end">
                  <IconButton onClick={() => null}>
                    <SearchRounded />
                  </IconButton>
                </InputAdornment>
              ),
            }}
            variant="outlined"
            disabled={shouldShowEmpty}
          />
          <Stack spacing={1} direction="row" alignItems="center">
            <Divider orientation="vertical" flexItem />
            <FilterAltRounded htmlColor="shades.900" fontSize="medium" />
          </Stack>
          <Select
            disabled={shouldShowEmpty}
            className={styles.TypeSelect}
            size="small"
            variant="outlined"
            value={type}
            onChange={({ target }) => handleFilter({ type: target.value, page: 1 })}
          >
            {[ALL_TYPE, ...PLAYER_TYPES.filter(($type) => $type.selfServe)].map((option) => (
              <MenuItem value={option} key={option.id}>
                {option.name}
              </MenuItem>
            ))}
          </Select>

          <Autocomplete
            disabled={shouldShowEmpty}
            className={styles.HubSelect}
            value={publisher}
            options={publishersOptions || []}
            loading={!publishersOptions}
            size="small"
            onChange={(_, selectedHPublisher) => handleFilter({ publisher: selectedHPublisher, page: 1 })}
            onOpen={() => dispatch(getPublishersOptionsAction(''))}
            onInputChange={(_, searchText) => dispatch(getPublishersOptionsAction(searchText))}
            renderInput={(params) => (
              <TextField {...params} data-id="site" value="" variant="outlined" placeholder="Choose Hub" />
            )}
          />
        </Stack>
      }
      renderActions={
        <Stack direction="row">
          {canCreatePlayer && (
            <Tooltip title="Add Player">
              <>
                <Button
                  size="small"
                  startIcon={<AddRounded />}
                  onClick={({ currentTarget }) => setAnchorEl(currentTarget)}
                >
                  Player
                </Button>
                <Menu anchorEl={anchorEl} open={open} onClose={() => setAnchorEl(null)}>
                  {typesOptions.map((typeOption) => (
                    <MenuItem
                      key={typeOption.id}
                      onClick={() => {
                        dispatch(setAction({ newPlayerType: typeOption }));
                        router.push(`/player/${typeOption.id}/new`);
                      }}
                    >
                      {typeOption.name}
                    </MenuItem>
                  ))}
                </Menu>
              </>
            </Tooltip>
          )}
        </Stack>
      }
    >
      {shouldShowEmpty ? (
        <Empty />
      ) : (
        <CommonTable
          configHeaders={TABLE_HEADER}
          configRenderRow={(row) => (
            <TableRow
              className={styles.Row}
              key={row.id}
              hover
              role="checkbox"
              onClick={() => {
                router.push(`/player/${row.type}/${row.id}`);
              }}
            >
              {TABLE_HEADER.map(({ id }) => renderTableCell(id, row))}
            </TableRow>
          )}
          data={data || []}
          selected={[]}
          sortBy={sortBy}
          sortOrder={sortOrder}
          totalCount={totalCount}
          page={page}
          rowsPerPage={pageSize}
          onSelectDeselectAllRows={() => {}}
          onSelectDeselectRow={() => {}}
          onFilter={handleFilter}
        />
      )}
      {showEmbedPopup && (
        <EmbedCodePopup
          embedCode={embedCode}
          onClose={() => {
            setShowEmbedPopup(false);
            setSelectedEmbedCodeType(EMBED_CODE_TYPES[0]);
          }}
          title="Player Embed Code"
          showAspectRatio={!isDisabledEmbedCodeAspectRatio}
          showEmbedCodeTypes={showEmbedCodeType}
          isAspectRatioDisabled={isDisabledEmbedCodeAspectRatio}
          selectedAspectRatio={aspectRatio}
          handleAspectRatioChange={(aspectRatioObj) => {
            dispatch(setAspectRatio({ aspectRatioObj, id: selectedPlayerId }));
          }}
          selectedEmbedCodeType={selectedEmbedCodeType}
          handleEmbedCodeTypeChange={(embedCodeTypeObj) => {
            setSelectedEmbedCodeType(embedCodeTypeObj);
            dispatch(setEmbedCodeByTypeAction({ embedCodeTypeObj, id: selectedPlayerId }));
          }}
        />
      )}
      {showDeleteDialog && (
        <Dialog
          aria-labelledby="delete-dialog-title"
          open={showDeleteDialog}
          maxWidth="sm"
          onClose={() => setShowDeleteDialog(false)}
        >
          <DialogTitle>Delete Action</DialogTitle>
          <DialogContent>
            <Typography variant="body2" color="text.primary">
              Are you sure you want to delete the player?
            </Typography>
          </DialogContent>

          <DialogActions>
            <Button
              size="small"
              onClick={() => {
                setShowDeleteDialog(false);
              }}
              variant="outlined"
            >
              Cancel
            </Button>
            <Button
              size="small"
              variant="contained"
              color="error"
              onClick={() => {
                dispatch(deletePlayerAction({ id: selectedPlayerId }));
                setShowDeleteDialog(false);
              }}
            >
              Delete
            </Button>
          </DialogActions>
        </Dialog>
      )}
    </CommonList>
  );
}

export default Players;
