import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import dayjs from 'dayjs';
import timezonePlugin from 'dayjs/plugin/timezone';
import utcPlugin from 'dayjs/plugin/utc';
import { useRouter } from 'next/router';
import { AddRounded, ExpandMoreRounded } from '@mui/icons-material';

import {
  PROVIDER_CREATE_URL_AZURE,
  PROVIDER_CREATE_URL_GOOGLE,
  PROVIDER_CREATE_URL_OKTA,
  PROVIDER_VALUE_AZURE,
  PROVIDER_VALUE_GOOGLE,
  PROVIDER_VALUE_OKTA,
  PROVIDERS,
  STATUS_ACTIVE_VALUE,
  STATUS_DISABLED_VALUE,
} from '../constants';

import { getConfigHeaders } from '../helpers';
import * as computedState from '../helpers/computedState';
import * as selectors from '../redux/selectors';
import { getDataAction, setAction, setTableAction, statusAction } from '../redux/slices';
import { omitUndefinedProps } from '@/mui/helpers';

import CommonList from '@/modules/@common/List';
import CommonTable from '@/modules/@common/Table';
import Empty from './Empty/Empty';
import { Button, Checkbox, Menu, MenuItem, Stack, TableCell, TableRow, Tooltip } from '@/mui/components';

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

dayjs.extend(utcPlugin);
dayjs.extend(timezonePlugin);

const getProviderLabel = (value) => PROVIDERS.find((provider) => provider.value === value)?.label;

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

  const [showCreateSsoProviderList, setShowCreateSsoProviderList] = useState(null);
  const [showActions, setShowActions] = useState(null);

  const data = useSelector(selectors.dataSelector);
  const page = useSelector(selectors.pageSelector);
  const pageSize = useSelector(selectors.pageSizeSelector);
  const totalCount = useSelector(selectors.totalCountSelector);
  const sortBy = useSelector(selectors.sortBySelector);
  const sortOrder = useSelector(selectors.sortOrderSelector);
  const selected = useSelector(selectors.selectedSelector);

  const shouldShowEmpty = useSelector(computedState.shouldShowEmpty);

  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$,
        }),
      ),
    );

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

  const handleNewProvide = (provider) => {
    router.push(`/sso/${provider}`);
  };

  const handleSelectDeselectAllRows = (checked) => {
    dispatch(
      setTableAction({
        selected: checked ? data.map((r) => r.id) : [],
      }),
    );
  };

  const handleSelectDeselectRow = (rowId) => {
    const selectedIndex = selected.indexOf(rowId);
    let newSelected = [];

    if (selectedIndex === -1) {
      newSelected = newSelected.concat(selected, rowId);
    } else if (selectedIndex === 0) {
      newSelected = newSelected.concat(selected.slice(1));
    } else if (selectedIndex === selected.length - 1) {
      newSelected = newSelected.concat(selected.slice(0, -1));
    } else if (selectedIndex > 0) {
      newSelected = newSelected.concat(selected.slice(0, selectedIndex), selected.slice(selectedIndex + 1));
    }

    dispatch(
      setTableAction({
        selected: newSelected,
      }),
    );
  };

  const handleChangeStatus = (status) => {
    dispatch(statusAction({ ids: selected, status }));
    dispatch(setTableAction({ selected: [] }));
    setShowActions('');
  };

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

  return (
    <CommonList
      title="Single Sign-On"
      renderFilters={
        <Stack direction="row" alignItems="center" spacing={2}>
          <Stack spacing={1} direction="row" alignItems="center">
            <Button
              size="small"
              color="neutral"
              variant="outlined"
              disabled={!selected.length}
              endIcon={<ExpandMoreRounded />}
              onClick={(event) => setShowActions(event.currentTarget)}
            >
              Actions
            </Button>
            {showActions && (
              <Menu open anchorEl={showActions} onClose={() => setShowActions('')}>
                <MenuItem onClick={() => handleChangeStatus(STATUS_ACTIVE_VALUE)}>Activate</MenuItem>
                <MenuItem onClick={() => handleChangeStatus(STATUS_DISABLED_VALUE)}>Deactivate</MenuItem>
              </Menu>
            )}
          </Stack>
        </Stack>
      }
      renderActions={
        <Tooltip title="Create SSO">
          <>
            <Button
              size="small"
              variant="contained"
              color="primary"
              startIcon={<AddRounded />}
              onClick={({ currentTarget }) => setShowCreateSsoProviderList(currentTarget)}
            >
              SSO
            </Button>
            <Menu
              anchorEl={showCreateSsoProviderList}
              open={Boolean(showCreateSsoProviderList)}
              onClose={() => setShowCreateSsoProviderList(null)}
            >
              <MenuItem onClick={() => handleNewProvide(PROVIDER_CREATE_URL_GOOGLE)}>
                {getProviderLabel(PROVIDER_VALUE_GOOGLE)}
              </MenuItem>
              <MenuItem onClick={() => handleNewProvide(PROVIDER_CREATE_URL_AZURE)}>
                {getProviderLabel(PROVIDER_VALUE_AZURE)}
              </MenuItem>
              <MenuItem onClick={() => handleNewProvide(PROVIDER_CREATE_URL_OKTA)}>
                {getProviderLabel(PROVIDER_VALUE_OKTA)}
              </MenuItem>
            </Menu>
          </>
        </Tooltip>
      }
    >
      {shouldShowEmpty ? (
        <Empty />
      ) : (
        <CommonTable
          enableBulkActions
          configHeaders={getConfigHeaders()}
          configRenderRow={(row, selectedRows, onSelectDeselectRow) => {
            const isItemSelected = selectedRows.includes(row.id);
            return (
              <TableRow
                className={styles.Row}
                key={row.id}
                hover
                onClick={() => router.push(`/sso/${row.id}`)}
                role="checkbox"
                aria-checked={isItemSelected}
                selected={isItemSelected}
              >
                <TableCell padding="checkbox" align="center">
                  <Checkbox
                    color="primary"
                    checked={isItemSelected}
                    onClick={(e) => {
                      e.stopPropagation();
                      onSelectDeselectRow(row.id);
                    }}
                  />
                </TableCell>
                <TableCell>
                  <div className={styles.NoWrap}>{row.id}</div>
                </TableCell>
                <TableCell>
                  <div className={styles.NoWrap}>{row.displayName}</div>
                </TableCell>
                <TableCell>
                  <div className={styles.NoWrap}>{getProviderLabel(row.provider)}</div>
                </TableCell>
                <TableCell>
                  <div className={styles.NoWrap}>{row.onlyExisting ? 'Only existing users' : 'All users'}</div>
                </TableCell>
                <TableCell>
                  <div className={styles.NoWrap}>{row.status > 0 ? 'Active' : 'Disabled'}</div>
                </TableCell>
                <TableCell>
                  <div className={styles.NoWrap}>{row.updatedBy}</div>
                </TableCell>
                <TableCell>
                  <div className={styles.NoWrap}>{dayjs(row.updatedAt).format('MMM D, YYYY hh:mm A')}</div>
                </TableCell>
              </TableRow>
            );
          }}
          data={data || []}
          sortBy={sortBy}
          sortOrder={sortOrder}
          totalCount={totalCount}
          page={page}
          rowsPerPage={pageSize}
          onFilter={handleFilter}
          selected={selected}
          onSelectDeselectAllRows={handleSelectDeselectAllRows}
          onSelectDeselectRow={handleSelectDeselectRow}
        />
      )}
    </CommonList>
  );
}

export default List;
