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

import { PCN_DELETE_FORMS_EDITOR, PCN_FORMS_GET_REPORT, PCN_POST_FORMS_EDITOR } from '@/modules/@common/acl/constants';
import { SORT_ASC, SORT_DESC } from '@/modules/@common/constants/sort';
import { FORM_DOWNLOAD_STATUS_START, SEARCH_TEXT_MAX_LENGTH } from '@/modules/forms/constants';
import { STATUS_ACTIVE, STATUS_OPTIONS, TABLE_HEADER } from '@/modules/forms/forms/constants';

import {
  downloadFormDataAction,
  getFormsAction,
  getSiteOptionsAction,
  setFieldAction,
  toArchiveAction,
} from '../redux/slices';
import { hasPermission } from '@/modules/@common/user/helpers';
import { getUserPermissionsSelector } from '@/modules/@common/user/redux/selectors';
import * as formsSelector from '@/modules/forms/forms/redux/selectors';

import { TableCellActions } from '@/modules/@common/Table';
import DownloadResponse from '@/modules/forms/common/components/DownloadResponse';
import TemplateGallery from '@/modules/forms/forms/components/TemplateGallery';
import {
  Autocomplete,
  Button,
  CircularProgress,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  Divider,
  Grid,
  IconButton,
  InputAdornment,
  Stack,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TablePagination,
  TableRow,
  TableScroll,
  TableSortLabel,
  TextField,
  Tooltip,
  Typography,
} from '@/mui/components';

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

const getStatusLabel = (value) => STATUS_OPTIONS.find((status) => status.value === value)?.label;

function Forms() {
  const router = useRouter();
  const [downloadResponseFrom, setDownloadResponseFrom] = useState(null);
  const [archiveConfirmForm, setArchiveConfirmForm] = useState(null);
  const [isOpenTemplateGallery, setIsOpenTemplateGallery] = useState(false);
  const dispatch = useDispatch();

  const forms = useSelector(formsSelector.formsSelector);
  const page = useSelector(formsSelector.pageSelector);
  const totalCount = useSelector(formsSelector.totalCountSelector);
  const rowsPerPage = useSelector(formsSelector.rowsPerPageSelector);
  const search = useSelector(formsSelector.searchSelector);
  const sortBy = useSelector(formsSelector.sortBySelector);
  const sortOrder = useSelector(formsSelector.sortOrderSelector);
  const status = useSelector(formsSelector.statusSelector);
  const site = useSelector(formsSelector.siteSelector);
  const siteOptions = useSelector(formsSelector.siteOptionsSelector);
  const shouldShowDownloadTryRequestOverConfirm = useSelector(
    formsSelector.shouldShowDownloadTryRequestOverConfirmSelector,
  );
  const isFormDownloadInProgress = useSelector(formsSelector.isFormDownloadInProgressSelector);

  const userPermissions = useSelector(getUserPermissionsSelector);

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

  const strippedHtml = (text) => {
    const strippedTag = text.replace(/(<([^>]+)>)/gi, '');
    const strippedEntities = strippedTag.replace(/&#{0,1}[a-z0-9]+;/gi, '');

    return strippedEntities;
  };

  const handleFilter = (filterObject) => {
    dispatch(setFieldAction(filterObject));
    dispatch(getFormsAction());
  };

  const handleArchiveConfirm = () => {
    dispatch(toArchiveAction(archiveConfirmForm.id));
    setArchiveConfirmForm(null);
  };

  const handleDownloadForm = (startDate) => {
    dispatch(
      downloadFormDataAction({
        formId: downloadResponseFrom.id,
        startDate,
        status: FORM_DOWNLOAD_STATUS_START,
      }),
    );
    setDownloadResponseFrom(null);
  };

  const handleCloseRetryConfirm = () => {
    dispatch(
      setFieldAction({
        shouldShowDownloadTryRequestOverConfirm: false,
      }),
    );
  };

  // todo: migrate to <CommonList />
  return (
    <div>
      <Grid container alignItems="center" justifyContent="center" className={styles.Title}>
        <Grid item xs={12}>
          <Typography variant="h6" color="text.primary" fontWeight={400}>
            Forms
          </Typography>
        </Grid>
      </Grid>
      <Grid container alignItems="center" justifyContent="center" className={styles.Controls}>
        <Grid container alignItems="center" justifyContent="space-between">
          <Grid item container xs={8}>
            <Grid item>
              <TextField
                id="search"
                size="small"
                value={search}
                className={styles.Search}
                onChange={({ target }) => handleFilter({ search: target.value, page: 1 })}
                placeholder="Search"
                inputProps={{
                  autoComplete: 'off',
                  maxLength: SEARCH_TEXT_MAX_LENGTH,
                }}
                InputProps={{
                  endAdornment: (
                    <InputAdornment position="end">
                      <IconButton onClick={() => null}>
                        <SearchRounded />
                      </IconButton>
                    </InputAdornment>
                  ),
                }}
                variant="outlined"
              />
            </Grid>
            <Grid item className={styles.FilterSeparator}>
              <Stack spacing={1} direction="row" alignItems="center">
                <Divider orientation="vertical" flexItem />
                <FilterAltRounded color="shades.900" fontSize="medium" />
              </Stack>
            </Grid>
            <Grid item className={styles.FilterStatusControl}>
              <Autocomplete
                className={styles.StatusSelect}
                disableClearable
                value={STATUS_OPTIONS.find((s) => s.value === status) ?? ''}
                options={STATUS_OPTIONS}
                size="small"
                onChange={(e, selected$) => handleFilter({ status: selected$?.value ?? '', page: 1 })}
                renderInput={(params) => <TextField {...params} placeholder="Status" />}
              />
            </Grid>
            <Grid item className={styles.FilterSiteControl}>
              <Autocomplete
                id="site"
                value={site}
                options={siteOptions || []}
                loading={!siteOptions}
                size="small"
                onChange={(e, selectedSite) => handleFilter({ site: selectedSite, page: 1 })}
                onOpen={() => dispatch(getSiteOptionsAction(''))}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    data-id="site"
                    value=""
                    variant="outlined"
                    placeholder="Hub"
                    onChange={({ target }) => dispatch(getSiteOptionsAction(target.value))}
                  />
                )}
              />
            </Grid>
          </Grid>
          <Grid item container xs={4} justifyContent="flex-end">
            {hasPermission(PCN_POST_FORMS_EDITOR, userPermissions) && (
              <Button
                size="small"
                variant="contained"
                color="primary"
                onClick={() => {
                  setIsOpenTemplateGallery(true);
                }}
                startIcon={<AddRounded />}
              >
                Form
              </Button>
            )}
          </Grid>
        </Grid>
      </Grid>
      <Grid container className={styles.TableWrapper}>
        <TableContainer>
          <TableScroll>
            <Table size="large">
              <TableHead>
                <TableRow>
                  {TABLE_HEADER.map((header) => (
                    <TableCell
                      padding={header.padding}
                      autoWidth={header.autoWidth}
                      width={header.width ?? 'inherit'}
                      data-id={`header-${header.id}`}
                      key={header.id}
                      sortDirection={sortBy === header.id ? sortOrder.toLowerCase() : false}
                    >
                      {header.sortable && (
                        <TableSortLabel
                          active={sortBy === header.id}
                          direction={sortBy === header.id ? sortOrder.toLowerCase() : SORT_ASC}
                          onClick={() =>
                            handleFilter({
                              sortBy: header.id,
                              sortOrder: sortOrder === SORT_ASC ? SORT_DESC : SORT_ASC,
                              page: 1,
                            })
                          }
                        >
                          {header.label}
                        </TableSortLabel>
                      )}

                      {!header.sortable && header.label}
                    </TableCell>
                  ))}
                </TableRow>
              </TableHead>
              <TableBody>
                {forms.map((row) => (
                  <TableRow hover onClick={() => router.push(`/forms/${row.id}`)} key={row.id} className={styles.Row}>
                    <TableCell component="th" scope="row">
                      {row.id}
                    </TableCell>
                    <TableCell component="th" scope="row">
                      <div className={styles.NoWrap}>{row.name}</div>
                    </TableCell>
                    <TableCell component="th" scope="row">
                      <div className={styles.NoWrap}>{strippedHtml(row.title)}</div>
                    </TableCell>
                    <TableCell component="th" scope="row">
                      <div className={styles.NoWrap}>{row.publisher?.name}</div>
                    </TableCell>
                    <TableCell component="th" scope="row">
                      {getStatusLabel(row.status)}
                    </TableCell>
                    <TableCell component="th" scope="row">
                      <div className={styles.NoWrap}>{row.updatedBy}</div>
                    </TableCell>
                    <TableCell component="th" scope="row">
                      <div className={styles.NoWrap}>{dayjs(row.updatedAt).format('MMM D, YYYY hh:mm A')}</div>
                    </TableCell>
                    <TableCellActions>
                      {isFormDownloadInProgress && <CircularProgress color="primary" size="xSmall" />}
                      {hasPermission(PCN_FORMS_GET_REPORT, userPermissions) && !isFormDownloadInProgress && (
                        <Tooltip title="Download form response" disableInteractive>
                          <IconButton
                            size="small"
                            onClick={(e) => {
                              e.stopPropagation();
                              setDownloadResponseFrom(row);
                            }}
                          >
                            <FileDownloadRounded />
                          </IconButton>
                        </Tooltip>
                      )}
                      {hasPermission(PCN_POST_FORMS_EDITOR, userPermissions) && (
                        <Tooltip title="Duplicate form" disableInteractive>
                          <IconButton
                            size="small"
                            onClick={(e) => {
                              e.stopPropagation();
                              router.push(`/forms/${row.id}/duplicate`);
                            }}
                          >
                            <ContentCopyRounded />
                          </IconButton>
                        </Tooltip>
                      )}
                      {hasPermission(PCN_DELETE_FORMS_EDITOR, userPermissions) && row.status === STATUS_ACTIVE && (
                        <Tooltip title="Archive form" disableInteractive>
                          <IconButton
                            size="small"
                            onClick={(e) => {
                              e.stopPropagation();
                              setArchiveConfirmForm(row);
                            }}
                          >
                            <Inventory2Rounded />
                          </IconButton>
                        </Tooltip>
                      )}
                    </TableCellActions>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </TableScroll>
          {!!totalCount && (
            <TablePagination
              rowsPerPageOptions={[10, 15, 25]}
              count={totalCount}
              rowsPerPage={rowsPerPage}
              page={page}
              onPageChange={(event, selectedPage) => handleFilter({ page: selectedPage })}
              onRowsPerPageChange={(event) =>
                handleFilter({
                  rowsPerPage: parseInt(event.target.value, 10),
                  page: 1,
                })
              }
              component="div"
            />
          )}
        </TableContainer>
      </Grid>

      {!!downloadResponseFrom?.id && (
        <DownloadResponse open onDownload={handleDownloadForm} onClose={() => setDownloadResponseFrom(null)} />
      )}

      <Dialog open={!!archiveConfirmForm?.id} onClose={() => setArchiveConfirmForm(null)} maxWidth="sm">
        <DialogTitle>Archive Confirm</DialogTitle>
        <DialogContent>{`Are you sure you want to archive form "${archiveConfirmForm?.name}" ?`}</DialogContent>
        <DialogActions>
          <Button size="small" variant="outlined" color="primary" onClick={() => setArchiveConfirmForm(null)}>
            Cancel
          </Button>
          <Button size="small" variant="contained" color="primary" onClick={handleArchiveConfirm}>
            Archive
          </Button>
        </DialogActions>
      </Dialog>

      <Dialog open={shouldShowDownloadTryRequestOverConfirm} onClose={handleCloseRetryConfirm} maxWidth="lg">
        <DialogTitle>The process is taking longer than expected.</DialogTitle>
        <DialogContent>
          <Typography variant="body1" color="text.primary" fontWeight={500}>
            You’ll receive the report to your email when ready.
          </Typography>
          <Typography variant="body1" color="text.primary" fontWeight={400}>
            While this process may take some time, you can continue to work in the AnyClip Platform.
          </Typography>
        </DialogContent>
        <DialogActions>
          <Button size="small" variant="outlined" color="primary" onClick={handleCloseRetryConfirm}>
            Cancel
          </Button>
          <Button size="small" variant="contained" color="primary" onClick={handleCloseRetryConfirm}>
            Got It
          </Button>
        </DialogActions>
      </Dialog>

      <TemplateGallery isOpen={isOpenTemplateGallery} onClose={() => setIsOpenTemplateGallery(false)} />
    </div>
  );
}

export default Forms;
