import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useDispatch, useSelector, useStore } from 'react-redux';
import { useRouter } from 'next/router';
import { Add, Delete, SearchRounded, UploadOutlined } from '@mui/icons-material';

import { PCN_GET_MARKETPLACE_DASHBOARD } from '@/modules/@common/acl/constants';

import * as selectors from '../../redux/selectors';
import * as actions from '../../redux/slices';
import { getInputPropsByName } from '@/modules/@common/Form/helpers';
import { hasPermission } from '@/modules/@common/user/helpers';
import { getUserPermissionsSelector } from '@/modules/@common/user/redux/selectors';
import { getNextId } from '@/modules/marketplace/common/helpers';

import { Form, FormContent, FormGroupTitle, FormRow, FormRowItem, FormSection } from '@/modules/@common/Form';
import ChipInput from '../../../common/ChipInput';
import LineItem from './LineItem';
import FormLineItem from './LineItem/FormLineItem';
import {
  Autocomplete,
  Button,
  IconButton,
  InputAdornment,
  Stack,
  TablePagination,
  TextField,
  Tooltip,
  Typography,
} from '@/mui/components';
import { CustomCsvFilled } from '@/mui/components/CustomIcon';

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

function KeyListForm() {
  const store = useStore();
  const dispatch = useDispatch();

  const userPermissions = useSelector(getUserPermissionsSelector);
  const scheme = useSelector(selectors.schemeSelector);

  const name = useSelector(selectors.nameSelector);
  const demandAccount = useSelector(selectors.demandAccountSelector);
  const demandAccountOptions = useSelector(selectors.demandAccountOptionsSelector);
  const searchKeys = useSelector(selectors.searchKeysSelector);
  const keys = useSelector(selectors.keysSelector);
  const keysPage = useSelector(selectors.keysPageSelector);
  const keysRowsPerPage = useSelector(selectors.keysRowsPerPageSelector);
  const bulkKeys = useSelector(selectors.bulkKeysSelector);
  const userDemandAccounts = useSelector(selectors.userDemandAccountsSelector);

  const isAdminMP = hasPermission(PCN_GET_MARKETPLACE_DASHBOARD, userPermissions);

  const router = useRouter();
  const fileInputRef = useRef(null);
  const [totalKeys, setTotalKeys] = useState(false);
  const [showNewForm, toggleNewFrom] = useState(false);

  const { id } = router.query;
  const isCreateForm = id === 'new';

  const isDuplicate = 'duplicate' in router.query;

  const clearForm = () => {
    dispatch(actions.setInitialFormAction());
  };

  useEffect(() => {
    clearForm();
    if (!isCreateForm) {
      dispatch(actions.getKeyListByIdAction({ id, isDuplicate }));
    }

    if (isAdminMP) {
      dispatch(actions.getDemandAccountsAction());
    }
  }, []);

  const keysData = useMemo(() => {
    let computedKeys = [...keys];

    if (searchKeys?.length) {
      computedKeys = computedKeys.filter((key) => key.name.toLowerCase().includes(searchKeys.toLowerCase()));
    }

    setTotalKeys(computedKeys.length);

    return computedKeys.slice(keysPage * keysRowsPerPage, keysPage * keysRowsPerPage + keysRowsPerPage);
  }, [keys, searchKeys, keysPage, keysRowsPerPage]);

  const isKeysSelected = () => keys.some((o) => o.checked);

  const handleCsvParse = ({ target }) => {
    const file = target.files[0];
    const fileReader = new FileReader();

    fileReader.onloadend = () => {
      const rawContent = fileReader.result;
      const content = rawContent.split('\n');

      dispatch(
        actions.setFieldAction({
          bulkKeys: content.filter(Boolean).map((item) => item.replace(/\r/g, '').trim()),
        }),
      );
    };
    fileReader.readAsText(file);

    fileInputRef.current.value = '';
  };

  const handleRemoveKeys = () => {
    dispatch(
      actions.setFieldAction({
        keys: keys.filter((o) => !o.checked),
      }),
    );
  };

  const handleBulkAddKeys = () => {
    const newBulkKeys = bulkKeys
      ?.map((item, index) => ({
        id: getNextId(keys) + index,
        name: item,
      }))
      .reverse();
    dispatch(
      actions.setFieldAction({
        keys: [...newBulkKeys, ...keys],
      }),
    );
    dispatch(actions.setFieldAction({ bulkKeys: [] }));
  };

  const handleBulkRemoveKeys = () => {
    dispatch(
      actions.setFieldAction({
        keys: keys.filter((key) => !bulkKeys?.includes(key.name)),
      }),
    );
    dispatch(actions.setFieldAction({ bulkKeys: [] }));
  };

  const handleSubmit = () => {
    const state = store.getState();
    const allProps = selectors.fullAccessToStoreFieldsForValidation(state);

    const { validation, errorList } = actions.validateFields(
      selectors.schemeSelector(state).map(({ fieldName }) => fieldName),
      allProps,
    );

    if (errorList.length) {
      const errorField = errorList[0];

      dispatch(actions.setScrollToFieldNameAction(errorField.fieldName));
    } else if (isCreateForm || isDuplicate) {
      dispatch(actions.createKeyListAction());
    } else {
      dispatch(actions.updateKeyListAction({ id }));
    }

    dispatch(actions.setErrorByPropAction(validation));
  };

  const headerText = isCreateForm ? 'Adding New Value List' : `${name} Value List`;

  return (
    <div className={styles.Wrapper}>
      <Stack direction="column" fullWidth justifyContent="center" className={styles.Title}>
        <Typography component="div" variant="h6" noWrap>
          {headerText?.length > 50 ? (
            <Tooltip title={headerText}>
              <span>{`${headerText.substring(0, 50)}...  Value List`}</span>
            </Tooltip>
          ) : (
            headerText
          )}
        </Typography>
      </Stack>
      <Stack
        spacing={1}
        fullWidth
        direction="row"
        alignItems="center"
        justifyContent="space-between"
        className={styles.Controls}
      >
        <div />

        <Stack spacing={2} justifyContent="flex-end" alignItems="center" direction="row">
          <Button
            size="small"
            onClick={() => {
              router.back();
              clearForm();
            }}
            variant="outlined"
            data-id="cancelButton"
          >
            Cancel
          </Button>
          <Button
            size="small"
            variant="contained"
            color="primary"
            data-id="saveButton"
            disabled={!keys?.length}
            onClick={handleSubmit}
          >
            Save
          </Button>
        </Stack>
      </Stack>
      <Form>
        <FormContent>
          <FormSection>
            <FormGroupTitle>Basic Setting</FormGroupTitle>
            <FormRow label="Name">
              <TextField
                value={name}
                placeholder="Enter Name"
                size="small"
                onChange={({ target }) => {
                  dispatch(
                    actions.setFieldAction({
                      name: target.value,
                    }),
                  );
                }}
                {...getInputPropsByName(scheme, ['name'])}
                onFocus={() => dispatch(actions.removeErrorByPropAction(['name']))}
              />
            </FormRow>
            <FormRow label="Demand Partner">
              <Autocomplete
                size="small"
                autoSuggest
                options={
                  isAdminMP
                    ? demandAccountOptions
                    : userDemandAccounts.map((item) => ({ value: item?.id?.toString(), label: item?.name }))
                }
                value={demandAccount}
                onChange={(event, newValue) => {
                  dispatch(actions.setFieldAction({ demandAccount: newValue }));
                }}
                disabled={!(isCreateForm || isDuplicate)}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    size="small"
                    placeholder="Assign One Demand Partner"
                    onChange={(e) => {
                      if (isAdminMP) {
                        dispatch(actions.getDemandAccountsAction(e.target.value));
                      }
                    }}
                    {...getInputPropsByName(scheme, ['demandAccount'])}
                    onFocus={() => dispatch(actions.removeErrorByPropAction(['demandAccount']))}
                  />
                )}
              />
            </FormRow>
            <FormGroupTitle />
            <FormRow label="Search" justifyContent="space-between" fullWidth>
              <FormRowItem itemsInRow={2}>
                <TextField
                  data-id="search"
                  value={searchKeys}
                  placeholder="Search"
                  InputProps={{
                    endAdornment: (
                      <InputAdornment position="end">
                        <IconButton onClick={() => null}>
                          <SearchRounded />
                        </IconButton>
                      </InputAdornment>
                    ),
                  }}
                  variant="outlined"
                  size="small"
                  onChange={({ target }) => {
                    dispatch(
                      actions.setFieldAction({
                        searchKeys: target.value,
                      }),
                    );
                  }}
                />
              </FormRowItem>
              <Stack spacing={2} direction="row" alignItems="center">
                {isKeysSelected() && (
                  <Button
                    onClick={handleRemoveKeys}
                    color="error"
                    size="small"
                    square
                    variant="outlined"
                    shape="rounded"
                  >
                    <Delete />
                  </Button>
                )}
                <Button
                  variant="contained"
                  color="primary"
                  size="small"
                  startIcon={<Add />}
                  onClick={() => toggleNewFrom(true)}
                >
                  Add New Value
                </Button>
              </Stack>
            </FormRow>
            <FormRow label fullWidth>
              <Stack fullWidth>
                <LineItem
                  id="#"
                  name="Value Name"
                  hasItems={keysData.length}
                  isLabelRow
                  checked={keysData.length && keysData.every((o) => o.checked)}
                  onSelect={(data) => {
                    dispatch(
                      actions.setFieldAction({
                        keys: keys.map((o) =>
                          keysData?.find((key) => key.id === o.id) ? { ...o, checked: data.checked } : o,
                        ),
                      }),
                    );
                  }}
                />

                {showNewForm && (
                  <FormLineItem
                    id={getNextId(keys)}
                    onSubmit={(data) => {
                      toggleNewFrom(false);
                      dispatch(
                        actions.setFieldAction({
                          keys: [{ ...data }, ...keys],
                        }),
                      );
                    }}
                    onCancel={() => {
                      toggleNewFrom(false);
                    }}
                  />
                )}

                {keysData.map((key) => (
                  <LineItem
                    key={key.id}
                    id={key.id}
                    name={key.name}
                    checked={key.checked ?? false}
                    onSubmit={(data) => {
                      dispatch(
                        actions.setFieldAction({
                          keys: keys.map((o) => (o.id === data.id ? { ...data } : o)),
                        }),
                      );
                    }}
                    onRemove={(data) => {
                      dispatch(
                        actions.setFieldAction({
                          keys: keys.filter((o) => o.id !== data.id),
                        }),
                      );
                    }}
                    onSelect={(data) => {
                      dispatch(
                        actions.setFieldAction({
                          keys: keys.map((o) => (o.id === data.id ? { ...o, checked: data.checked } : o)),
                        }),
                      );
                    }}
                  />
                ))}

                {totalKeys > 5 && (
                  <TablePagination
                    component="div"
                    rowsPerPageOptions={[5, 10, 15]}
                    count={totalKeys}
                    rowsPerPage={keysRowsPerPage}
                    page={keysPage + 1}
                    onPageChange={(event, page) => {
                      dispatch(actions.setFieldAction({ keysPage: page - 1 }));
                    }}
                    onRowsPerPageChange={(event) => {
                      dispatch(actions.setFieldAction({ keysRowsPerPage: +event.target.value }));
                    }}
                  />
                )}

                {!keys.length && !showNewForm && (
                  <Typography
                    component="div"
                    align="center"
                    variant="caption"
                    color="text.secondary"
                    className={styles.EmptyKeys}
                  >
                    No values to show. Start adding them by clicking button below, or use Bulk Actions.
                  </Typography>
                )}
              </Stack>
            </FormRow>
            <FormGroupTitle>Bulk Actions</FormGroupTitle>
            <FormRow label="Upload CSV File">
              <Button
                variant="outlined"
                size="small"
                color="primary"
                shape="rounded"
                label="Upload CSV"
                component="label"
                startIcon={<CustomCsvFilled />}
                endIcon={<UploadOutlined />}
              >
                Upload CSV
                <input hidden accept=".csv" id={id} ref={fileInputRef} type="file" onChange={handleCsvParse} />
              </Button>
            </FormRow>
            <FormRow label="Add or Remove Values">
              <ChipInput
                placeholder="Enter Values"
                labels={bulkKeys}
                inputHint={bulkKeys?.length ? `${bulkKeys?.length} Values` : 'For creating press Enter'}
                onChange={({ labels }) => dispatch(actions.setFieldAction({ bulkKeys: labels }))}
              />
            </FormRow>
            <FormRow fullWidth justifyContent="flex-end">
              <Button variant="outlined" disabled={!bulkKeys.length} size="small" onClick={handleBulkRemoveKeys}>
                Remove Values
              </Button>
              <Button
                variant="contained"
                color="primary"
                size="small"
                disabled={!bulkKeys.length}
                onClick={handleBulkAddKeys}
                startIcon={<Add />}
              >
                Add Values
              </Button>
            </FormRow>
          </FormSection>
        </FormContent>
      </Form>
    </div>
  );
}

export default KeyListForm;
