import React, { useEffect, useState, useMemo, useCallback } from 'react';
import FarmCard from '../Components/FarmCard/FarmCard';
import { connect } from 'react-redux';
import * as userActions from '../redux/actions/user/user.action';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { BsSearch } from 'react-icons/bs';
import styles1 from '../assets/scss/tokens.module.scss';
import { FormControl, InputGroup, Tabs, Tab } from 'react-bootstrap';
import * as walletActions from '../redux/actions/wallet/wallet.action';
import Switch from '../Components/Ui/Switch/Switch';
import StakeModal from '../Components/Ui/Modals/StakeModal';
import UnstakeModal from '../Components/Ui/Modals/UnstakeModal';
import styles from '../assets/scss/partials/_farms.module.scss';
import FarmModals from '../Components/FarmPage/FarmModals';
import {
  closeFarmsStakeModal,
  closeFarmsUnstakeModal,
  openFarmsStakeModal,
  openFarmsUnstakeModal,
  populateEmptyFarmsData,
  toggleFarmsType,
  toggleStakedFarmsOnly,
} from '../redux/slices/farms/farms.slice';
import {
  getFarmsDataThunk,
  harvestOnFarmThunk,
  stakeOnFarmThunk,
  unstakeOnFarmThunk,
} from '../redux/slices/farms/farms.thunk';
import { populateFarmsWithoutData } from '../utils/farmsPageUtils';
import { FARM_SORT_OPTIONS, FARM_TAB } from '../constants/farmsPage';
import ConfirmTransaction from '../Components/WrappedAssets/ConfirmTransaction';
import { setLoader } from '../redux/slices/settings/settings.slice';
import { ReactComponent as StableswapGrey } from '../assets/images/SwapModal/Stableswap-grey.svg';
import { ReactComponent as StableswapImg } from '../assets/images/SwapModal/stableswap.svg';

const Farms = (props) => {
  const [sortValue, setSortValue] = useState(FARM_SORT_OPTIONS.APR);
  const [floaterValue, setFloaterValue] = useState({});
  const [searchValue, setSearchValue] = useState('');
  const [tabChange, setTabChange] = useState(FARM_TAB.ALL);
  const [isSelected, setIsSelected] = useState(false);
  const [isOpen, setIsOpen] = useState(false);
  const [showConfirmTransaction, setShowConfirmTransaction] = useState(false);

  function toggleHidden() {
    setIsOpen(!isOpen);
  }
  function setSelectTitle(e) {
    setSortValue(e.target.value);
    toggleHidden();
  }

  // * Initial Call
  useEffect(() => {
    if (props.activeFarms.length === 0 || props.inactiveFarms.length === 0) {
      const farmsWithoutData = populateFarmsWithoutData();
      props.populateEmptyFarmsData(farmsWithoutData);
    }
  }, []);

  const handleClose = () => {
    setShowConfirmTransaction(false);
  };

  useEffect(() => {
    const fetchData = () => {
      props.getFarmsData(props.isActiveOpen);
      props.getUserStakes(props.userAddress, 'FARMS', props.isActiveOpen);
      props.getHarvestValues(props.userAddress, 'FARMS', props.isActiveOpen);
      props.fetchUserBalances(props.userAddress);
    };

    fetchData();
    const backgroundRefresh = setInterval(() => {
      fetchData();
    }, 60 * 1000);

    return () => clearInterval(backgroundRefresh);
  }, [props.isActiveOpen, props.userAddress, props.rpcNode]);

  const sortFarmsFunc = useCallback(
    (a, b) => {
      if (sortValue === FARM_SORT_OPTIONS.APR) {
        return Number(a.values?.APR) < Number(b.values?.APR) ? 1 : -1;
      }

      if (sortValue === FARM_SORT_OPTIONS.TVL) {
        return Number(a.values?.totalLiquidty) < Number(b.values?.totalLiquidty) ? 1 : -1;
      }

      if (sortValue === FARM_SORT_OPTIONS.REWARDS) {
        const a1 = Number(a.values?.rewardRate * 2880);
        const b1 = Number(b.values?.rewardRate * 2880);
        return a1 < b1 ? 1 : -1;
      }

      return 0;
    },
    [sortValue],
  );

  const filterBySearch = useCallback(
    (farm) => farm.farmData.CARD_TYPE.toLowerCase().includes(searchValue.toLowerCase()),
    [searchValue],
  );

  const filterByTab = useCallback(
    (farm) => {
      if (tabChange === FARM_TAB.CTEZ) {
        return farm.farmData.CARD_TYPE.toLowerCase().includes('ctez');
      }
      if (tabChange === FARM_TAB.NEW) {
        return farm.farmData.bannerType?.includes('info');
      }
      if (tabChange === FARM_TAB.STABLE) {
        return (
          farm.farmData.farmType?.includes('veStableAMM') || farm.farmData.farmType?.includes('xtz')
        );
      }
      if (tabChange === FARM_TAB.YOU) {
        return props.userStakes[farm.farmData.CONTRACT]?.stakedAmount > 0;
      }

      return true;
    },
    [tabChange, props.userStakes],
  );

  const filterByStaked = useCallback(
    (farm) => {
      if (!props.isStakedOnlyOpen) return true;

      return props.userStakes[farm.farmData.CONTRACT]?.stakedAmount > 0;
    },
    [props.isStakedOnlyOpen, props.userStakes],
  );

  const farmsToRender = useMemo(() => {
    const farmsInView = props.isActiveOpen
      ? props.activeFarms.slice()
      : props.inactiveFarms.slice();

    return farmsInView
      .filter(filterBySearch)
      .filter(filterByTab)
      .filter(filterByStaked)
      .sort(sortFarmsFunc);
  }, [
    filterBySearch,
    filterByTab,
    filterByStaked,
    sortFarmsFunc,
    props.activeFarms,
    props.inactiveFarms,
    props.isActiveOpen,
  ]);

  return (
    <>
      <div>
        <div>
          <div className={styles.header}>
            <Tabs
              className={`swap-container-tab ${styles.farmstab}`}
              mountOnEnter={true}
              unmountOnExit={true}
              onSelect={(e) => setTabChange(e)}
            >
              <Tab eventKey={FARM_TAB.ALL} title={FARM_TAB.ALL} />
              <Tab eventKey={FARM_TAB.NEW} title={FARM_TAB.NEW} />
              <Tab
                eventKey={FARM_TAB.STABLE}
                title={
                  <span>
                    <span className="mr-2">{FARM_TAB.STABLE}</span>
                    {tabChange === FARM_TAB.STABLE ? <StableswapImg /> : <StableswapGrey />}
                  </span>
                }
              />
              <Tab eventKey={FARM_TAB.YOU} title={FARM_TAB.YOU} />
            </Tabs>

            <div className={styles.selectForm}>
              <div className={styles.selectgroup}>
                <label htmlFor="button"> Sort by:</label>
                <button
                  id="button"
                  onClick={(ev) => toggleHidden(ev)}
                  className={`button ${styles.sortLabel}
                `}
                >
                  <span id="select-label">{sortValue}</span>
                  <span className={`material-icons ${styles.arrow} `}>keyboard_arrow_down</span>
                </button>

                <div
                  className={clsx(styles.dropdown, isOpen ? styles.show : styles.hidden)}
                  id="dropdown"
                >
                  <label className={` ${styles.sortby} ${styles.sortby} `}>SORT BY:</label>
                  <div className={styles.selectOption}>
                    <label className={styles.selectItem} htmlFor="select-apr">
                      {FARM_SORT_OPTIONS.APR}
                    </label>
                    <input
                      className={`option ${styles.option}`}
                      id="select-apr"
                      type="radio"
                      name="where"
                      value={FARM_SORT_OPTIONS.APR}
                      onClick={(ev) => setSelectTitle(ev)}
                    />
                  </div>
                  <div className={styles.selectOption}>
                    <label className={styles.selectItem} htmlFor="select-tvl">
                      {FARM_SORT_OPTIONS.TVL}
                    </label>
                    <input
                      className={`option ${styles.option}`}
                      id="select-tvl"
                      type="radio"
                      name="where"
                      value={FARM_SORT_OPTIONS.TVL}
                      onClick={(ev) => setSelectTitle(ev)}
                    />
                  </div>
                  <div className={styles.selectOption}>
                    <label className={styles.selectItem} htmlFor="select-rewards">
                      {FARM_SORT_OPTIONS.REWARDS}
                    </label>
                    <input
                      className={`option ${styles.option}`}
                      name="where"
                      id="select-rewards"
                      type="radio"
                      value={FARM_SORT_OPTIONS.REWARDS}
                      onClick={(ev) => setSelectTitle(ev)}
                    />
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div className={` mt-4 justify-between  ${styles.header2}`}>
            <div className={styles.leftDiv}>
              <InputGroup className={styles1.searchBar}>
                <InputGroup.Prepend>
                  <InputGroup.Text className="search-icon border-right-0">
                    <BsSearch />
                  </InputGroup.Text>
                </InputGroup.Prepend>
                <FormControl
                  placeholder="Search"
                  className={`shadow-none border-left-0 ${styles1.searchBox}`}
                  value={searchValue}
                  onChange={(ev) => setSearchValue(ev.target.value)}
                />
              </InputGroup>
            </div>
            <div className={styles.selectForm1}>
              <span className={styles.sortButton} onClick={() => setIsSelected(!isSelected)}>
                Sort
                <span className={clsx('material-icons', styles.arrow, isSelected && styles.rotate)}>
                  keyboard_arrow_up
                </span>
              </span>
            </div>
            <div>
              <div className={styles.rightDiv}>
                <div>
                  <Switch
                    value={props.isActiveOpen}
                    onChange={() => props.toggleFarmsType(!props.isActiveOpen)}
                    trueLabel={'Active'}
                    falseLabel={'Inactive'}
                    inverted={true}
                  />
                </div>
              </div>
            </div>
          </div>
          {isSelected && (
            <div className={`justify-between flex ${styles.mobileSort}`}>
              <div
                onClick={() => setSortValue(FARM_SORT_OPTIONS.APR)}
                className={clsx(
                  styles.sortButton,
                  sortValue === FARM_SORT_OPTIONS.APR ? styles.addbg : styles.removebg,
                )}
              >
                {FARM_SORT_OPTIONS.APR}
              </div>
              <div
                onClick={() => setSortValue(FARM_SORT_OPTIONS.TVL)}
                className={clsx(
                  styles.sortButton,
                  sortValue === FARM_SORT_OPTIONS.TVL ? styles.addbg : styles.removebg,
                )}
              >
                {FARM_SORT_OPTIONS.TVL}
              </div>
              <div
                onClick={() => setSortValue(FARM_SORT_OPTIONS.REWARDS)}
                className={clsx(
                  styles.sortButton,
                  sortValue === FARM_SORT_OPTIONS.REWARDS ? styles.addbg : styles.removebg,
                )}
              >
                {FARM_SORT_OPTIONS.REWARDS}
              </div>
            </div>
          )}
          <div className={styles.cardsContainer}>
            {farmsToRender?.map((farm) => {
              return (
                <FarmCard
                  key={`${farm.identifier}${props.isActiveOpen ? ' active' : ''}`}
                  harvestOnFarm={props.harvestOnFarm}
                  stakeOnFarm={props.stakeOnFarm}
                  openFarmsStakeModal={props.openFarmsStakeModal}
                  openFarmsUnstakeModal={props.openFarmsUnstakeModal}
                  connectWallet={props.connectWallet}
                  unstakeOnFarm={props.unstakeOnFarm}
                  isActiveOpen={props.isActiveOpen}
                  farmCardData={farm}
                  userStakes={props.userStakes}
                  harvestValueOnFarms={props.harvestValueOnFarms}
                  userAddress={props.userAddress}
                  currentBlock={props.currentBlock}
                  harvestOperation={props.harvestOperation}
                  theme={props.theme}
                  setShowConfirmTransaction={setShowConfirmTransaction}
                  setFloaterValue={setFloaterValue}
                  setLoader={props.setLoader}
                />
              );
            })}
          </div>
        </div>
      </div>
      <StakeModal
        walletBalances={props.walletBalances}
        isActiveOpen={props.isActiveOpen}
        modalData={props.stakeModal}
        open={props.stakeModal.open}
        onClose={() => props.closeFarmsStakeModal()}
        stakeOnFarm={props.stakeOnFarm}
        stakeOperation={props.stakeOperation}
        setShowConfirmTransaction={setShowConfirmTransaction}
        setFloaterValue={setFloaterValue}
        setLoader={props.setLoader}
      />
      <UnstakeModal
        modalData={props.unstakeModal}
        currentBlock={props.currentBlock}
        open={props.unstakeModal.open}
        onClose={() => {
          props.closeFarmsUnstakeModal();
        }}
        userStakes={props.userStakes}
        isActiveOpen={props.isActiveOpen}
        unstakeOnFarm={props.unstakeOnFarm}
        unstakeOperation={props.unstakeOperation}
        setShowConfirmTransaction={setShowConfirmTransaction}
        setFloaterValue={setFloaterValue}
        setLoader={props.setLoader}
      />
      <ConfirmTransaction
        show={showConfirmTransaction}
        theme={props.theme}
        content={
          floaterValue.type === 'Harvest'
            ? `${floaterValue.type} ${floaterValue.value} ${floaterValue.pair}  `
            : `${floaterValue.type} ${Number(floaterValue.value).toFixed(6)} ${
                floaterValue.pair
              } LP `
        }
        onHide={handleClose}
      />
      <FarmModals
        setLoader={props.setLoader}
        type={floaterValue.type}
        pair={floaterValue.pair}
        value={floaterValue.value}
        theme={props.theme}
        content={
          floaterValue.type === 'Harvest'
            ? `${floaterValue.type} ${floaterValue.value} ${floaterValue.pair}  `
            : `${floaterValue.type} ${Number(floaterValue.value).toFixed(6)} ${
                floaterValue.pair
              } LP `
        }
      />
    </>
  );
};

Farms.propTypes = {
  activeFarms: PropTypes.any,
  closeFarmsStakeModal: PropTypes.any,
  closeFarmsUnstakeModal: PropTypes.any,
  connectWallet: PropTypes.any,
  currentBlock: PropTypes.any,
  fetchUserBalances: PropTypes.any,
  getFarmsData: PropTypes.any,
  getHarvestValues: PropTypes.any,
  getUserStakes: PropTypes.any,
  harvestOnFarm: PropTypes.any,
  harvestOperation: PropTypes.any,
  harvestValueOnFarms: PropTypes.any,
  inactiveFarms: PropTypes.any,
  isActiveOpen: PropTypes.any,
  isStakedOnlyOpen: PropTypes.bool,
  openFarmsStakeModal: PropTypes.any,
  openFarmsUnstakeModal: PropTypes.any,
  populateEmptyFarmsData: PropTypes.any,
  rpcNode: PropTypes.any,
  stakeModal: PropTypes.any,
  stakeOnFarm: PropTypes.any,
  stakeOperation: PropTypes.any,
  toggleFarmsType: PropTypes.any,
  toggleStakedFarmsOnly: PropTypes.any,
  unstakeModal: PropTypes.any,
  unstakeOnFarm: PropTypes.any,
  unstakeOperation: PropTypes.any,
  userAddress: PropTypes.any,
  userStakes: PropTypes.any,
  walletAddress: PropTypes.string.isRequired,
  walletBalances: PropTypes.any,
  theme: PropTypes.any,
  setLoader: PropTypes.any,
};

const mapStateToProps = (state) => {
  return {
    userAddress: state.wallet.address,
    isActiveOpen: state.farms.isActiveOpen,
    isStakedOnlyOpen: state.farms.isStakedOnlyOpen,
    stakeOperation: state.farms.stakeOperation,
    activeFarms: state.farms.data.active,
    inactiveFarms: state.farms.data.inactive,
    activeFarmData: state.farms.active,
    inactiveFarmsData: state.farms.inactive,
    userStakes: state.user.stakes,
    harvestValueOnFarms: state.user.harvestValueOnFarms,
    unstakeOperation: state.farms.unstakeOperation,
    harvestOperation: state.farms.harvestOperation,
    currentBlock: state.user.currentBlock,
    walletBalances: state.user.balances,
    stakeModal: state.farms.stakeModal,
    unstakeModal: state.farms.unstakeModal,
    rpcNode: state.settings.rpcNode,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    connectWallet: () => dispatch(walletActions.connectWallet()),
    populateEmptyFarmsData: (farms) => dispatch(populateEmptyFarmsData(farms)),
    toggleFarmsType: (isActive) => dispatch(toggleFarmsType(isActive)),
    toggleStakedFarmsOnly: (isActive) => dispatch(toggleStakedFarmsOnly(isActive)),
    stakeOnFarm: (
      amount,
      farmIdentifier,
      isActive,
      position,
      setShowConfirmTransaction,
      setLoader,
    ) =>
      dispatch(
        stakeOnFarmThunk(
          amount,
          farmIdentifier,
          isActive,
          position,
          setShowConfirmTransaction,
          setLoader,
        ),
      ),
    harvestOnFarm: (farmIdentifier, isActive, position, setShowConfirmTransaction, setLoader) =>
      dispatch(
        harvestOnFarmThunk(
          farmIdentifier,
          isActive,
          position,
          setShowConfirmTransaction,
          setLoader,
        ),
      ),
    getFarmsData: (isActive) => dispatch(getFarmsDataThunk(isActive)),
    getUserStakes: (address, type, isActive) =>
      dispatch(userActions.getUserStakes(address, type, isActive)),
    getHarvestValues: (address, type, isActive) =>
      dispatch(userActions.getHarvestValues(address, type, isActive)),
    openFarmsStakeModal: (identifier, title, contractAddress, position) =>
      dispatch(
        openFarmsStakeModal({
          identifier,
          title,
          contractAddress,
          position,
        }),
      ),
    closeFarmsStakeModal: () => dispatch(closeFarmsStakeModal()),
    openFarmsUnstakeModal: (identifier, contractAddress, title, withdrawalFeeStructure, position) =>
      dispatch(
        openFarmsUnstakeModal({
          identifier,
          contractAddress,
          title,
          withdrawalFeeStructure,
          position,
        }),
      ),
    closeFarmsUnstakeModal: () => dispatch(closeFarmsUnstakeModal()),
    unstakeOnFarm: (
      stakesToUnstake,
      farmIdentifier,
      isActive,
      position,
      setShowConfirmTransaction,
      setLoader,
    ) =>
      dispatch(
        unstakeOnFarmThunk(
          stakesToUnstake,
          farmIdentifier,
          isActive,
          position,
          setShowConfirmTransaction,
          setLoader,
        ),
      ),
    fetchUserBalances: (address) => dispatch(userActions.fetchUserBalances(address)),
    setLoader: (value) => dispatch(setLoader(value)),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Farms);