import React, { useEffect } from 'react';
import { useDispatch, useSelector, useStore } from 'react-redux';
import classNames from 'clsx';
import dayjs from 'dayjs';
import { useRouter } from 'next/router';
import { ContentCopyRounded, InfoOutlined } from '@mui/icons-material';

import {
  CUSTOM_PARENT_STICKY_CLASS_NAME,
  FILTERS,
  FILTERS_SELF_SERVE,
  REFRESH_INTERVAL_TIME,
} from '../../common/constants';
import {
  BUDGETING,
  DEMAND_ADVERTISER_PAGE,
  DEMAND_TAG_FORMAT,
  DEMAND_TAG_PAGE,
  DEMAND_TAG_PRICING_TYPE,
  PAGES_WITH_REFRESH_TABLES,
  SUPPLY_SITE_PAGE,
  SUPPLY_TAG_PAGE,
  SUPPLY_TAG_PAGE_TABS_VAST,
} from '../constants';
import { PCN_GET_MARKETPLACE_DASHBOARD } from '@/modules/@common/acl/constants';
import { TYPE_SUCCESS } from '@/modules/@common/notify/constants';

import { useInterval } from '../../common/helpers/interval';
import * as selectors from '../redux/selectors';
import * as actions from '../redux/slices';
import copyToClipboard from '@/modules/@common/helpers/copy';
import { hasPermission } from '@/modules/@common/user/helpers';
import { getUserPermissionsSelector } from '@/modules/@common/user/redux/selectors';
import { showNotificationAction } from '@/modules/layout/redux/slices';

import DateSelect from '@/modules/marketplace/common/DateSelect';
import Header from '@/modules/marketplace/common/HeaderNew';
import AdvertiserSettings from './AdvertiserSettings';
import AdvertiserPricingTab from './AdvertiserSettings/components/AdvertiserPricingTab';
import Breadcrumbs from './Breadcrumbs';
import { BudgetingTab, FrequencyCapTab, PricingTab, SettingsTab, TargetingTab } from './DemandSettings';
import Main from './Main';
import ChangeAdFeeModal from './Modals/ChangeAdFeeModal';
import ChangeExpensesModal from './Modals/ChangeExpensesModal';
import ChangeRevShareModal from './Modals/ChangeRevShareModal';
import ChangeTierModal from './Modals/ChangeTierModal';
import ChangeViewabilityThresholdModal from './Modals/ChangeViewabilityThreshold';
import ConfirmFrequencyCapModal from './Modals/ConfirmFrequencyCapModal';
import WaterfallModal from './Modals/WaterfallModal';
import SupplyTagSettings from './SupplyTagSettings';
import AutomaticOptimization from './SupplyTagSettings/components/AutomaticOptimization';
import ExportTagTab from './SupplyTagSettings/components/ExportTagTab/ExportTagTab';
import usePageConfig from './usePageConfig';
import {
  Autocomplete,
  Button,
  Divider,
  FormControl,
  Grid,
  IconButton,
  MenuItem,
  Select,
  Stack,
  Tab,
  TabContent,
  Tabs,
  TextField,
  Tooltip,
  Typography,
} from '@/mui/components';
import { CustomCsvFilled } from '@/mui/components/CustomIcon';

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

export default function Account(props) {
  const store = useStore();
  const dispatch = useDispatch();

  const userPermissions = useSelector(getUserPermissionsSelector);

  const info = useSelector(selectors.infoSelector);
  const targeting = useSelector(selectors.targetingSelector);
  const activeTabIndex = useSelector(selectors.activeTabIndexSelector);
  const supply = useSelector(selectors.supplySelector);
  const settings = useSelector(selectors.settingsSelector);
  const filterByCountry = useSelector(selectors.filterByCountrySelector);
  const filterByDevice = useSelector(selectors.filterByDeviceSelector);
  const filterByDate = useSelector(selectors.filterByDateSelector);
  const filterByPlayer = useSelector(selectors.filterByPlayerSelector);
  const filterByPlayerOptions = useSelector(selectors.filterByPlayerOptionsSelector);
  const modal = useSelector(selectors.modalSelector);
  const isFormSubmitDisabled = useSelector(selectors.isFormSubmitDisabledSelector);

  const setFilterByDate = (o) => dispatch(actions.setFilterByDateAction(o));
  const closeModal = (o) => dispatch(actions.closeModalAction(o));
  const getDataForWaterfall = (o) => dispatch(actions.getDataForWaterfallAction(o));
  const getAccountsForWaterfall = (o) => dispatch(actions.getAccountsForWaterfallAction(o));
  const getLabelsForWaterfall = (o) => dispatch(actions.getLabelsForWaterfallAction(o));
  const setModalInfo = (o) => dispatch(actions.setModalInfoAction(o));
  const bulkCreateWaterfall = (o) => dispatch(actions.bulkCreateWaterfallAction(o));
  const updateTiers = (o) => dispatch(actions.updateTiersAction(o));
  const updateDemandTag = (o) => dispatch(actions.updateDemandTagAction(o));
  const bulkUpdateDemandTag = (o) => dispatch(actions.bulkUpdateDemandTagAction(o));
  const bulkUpdateSupplyTag = (o) => dispatch(actions.bulkUpdateSupplyTagAction(o));
  const bulkUpdateViewabilityThreshold = (o) => dispatch(actions.bulkUpdateViewabilityThresholdAction(o));

  const router = useRouter();
  const isAdminMP = hasPermission(PCN_GET_MARKETPLACE_DASHBOARD, userPermissions);

  const pageConfig = usePageConfig({ isAdminMP });

  const { resetInterval, stopInterval: stopRefreshInterval } = useInterval(() => {
    dispatch(actions.refreshPageDataByIntervalAction());
  }, REFRESH_INTERVAL_TIME);

  const resetRefreshInterval = () => {
    if (PAGES_WITH_REFRESH_TABLES.includes(pageConfig.type)) {
      resetInterval();
    }
  };

  let { tabs } = pageConfig;

  if (pageConfig.type === SUPPLY_TAG_PAGE && info?.accountType === 'VAST' && isAdminMP) {
    tabs = SUPPLY_TAG_PAGE_TABS_VAST;
  }

  if (pageConfig.type === DEMAND_TAG_PAGE && settings?.format === DEMAND_TAG_FORMAT.sponsored) {
    tabs = tabs.filter((item) => item.dataId !== 'demandTagFrequency');
  }

  const tabsContent = {
    main: <Main resetRefreshInterval={resetRefreshInterval} stopRefreshInterval={stopRefreshInterval} />,
    supplyTagSettings: <SupplyTagSettings isAdminMP={isAdminMP} />,
    demandTagSettings: <SettingsTab isAdminMP={isAdminMP} />,
    demandTagPricing: <PricingTab isAdminMP={isAdminMP} />,
    demandTagTargeting: <TargetingTab tabConfig={pageConfig?.targetingTabConfig} isAdminMP={isAdminMP} />,
    demandTagBudgeting: <BudgetingTab />,
    demandTagFrequency: <FrequencyCapTab />,
    exportSupplyTag: <ExportTagTab />,
    advertiserSettings: <AdvertiserSettings />,
    advertiserPricing: <AdvertiserPricingTab />,
    automaticOptimization: <AutomaticOptimization />,
  };

  const handleSubmitForm = () => {
    const state = store.getState();
    const upsert = () => pageConfig?.upsertAction?.();

    const formSubmitHandlers = {
      [DEMAND_ADVERTISER_PAGE]: () => {
        const allProps = selectors.fullAccessToStoreFieldsForValidation(state);
        const fields = selectors.advertiserSettingsValidationSchemeSelector(state).map(({ fieldName }) => fieldName);
        const { validation, errorList } = actions.advertiserSettingsValidationSlice.validateFields(fields, allProps);

        if (errorList.length) {
          const { tabId, fieldName } = errorList.find((e) => e.tabId === activeTabIndex) ?? errorList[0];
          const tabIndex = tabs.findIndex((t) => t.dataId === tabId);

          dispatch(actions.setActiveTabIndexAction(tabIndex));
          dispatch(actions.advertiserSettingsValidationSetScrollToFieldNameAction(fieldName));
        } else {
          upsert();
        }

        dispatch(actions.advertiserSettingsValidationSetErrorByPropAction(validation));
      },
      // Future forms can go here
      // Example:
      // [OTHER_PAGE_VALIDATION]: () => {
      //   console.log('Handle OTHER PAGE HERE form');
      //   upsert();
      // }
    };

    (formSubmitHandlers[pageConfig.type] ?? upsert)();
  };

  useEffect(() => {
    const handleVisibilityChange = () => {
      if (PAGES_WITH_REFRESH_TABLES.includes(pageConfig.type)) {
        if (document.hidden) {
          stopRefreshInterval();
        } else {
          resetRefreshInterval();
        }
      }
    };

    window.addEventListener('visibilitychange', handleVisibilityChange);

    return () => {
      window.removeEventListener('visibilitychange', handleVisibilityChange);
    };
  }, []);

  useEffect(() => {
    if (pageConfig) {
      dispatch(actions.setDefaultConfigAction(pageConfig.defaultConfig ?? {}));
      dispatch(actions.setFieldAction({ pageConfig }));

      dispatch(actions.getHubsAndDemandAccountsAction());

      if (!pageConfig.isCreatingNew) {
        dispatch(actions.getInfoAction(pageConfig.id));
        dispatch(actions.getTotalAction({ type: pageConfig.type }));
        dispatch(actions.getDataAction({ type: pageConfig.type }));
        dispatch(actions.getChartDataAction());

        if (PAGES_WITH_REFRESH_TABLES.includes(pageConfig.type)) {
          resetRefreshInterval();
        }
      }

      if (pageConfig.isCreatingNew || pageConfig.isDuplicate || !PAGES_WITH_REFRESH_TABLES.includes(pageConfig.type)) {
        stopRefreshInterval();
      }

      if (pageConfig.type === DEMAND_ADVERTISER_PAGE) {
        dispatch(actions.getCountriesListAction());
        dispatch(actions.getLabelsForTableFilterAction());
      }

      if (pageConfig.type === SUPPLY_SITE_PAGE) {
        dispatch(actions.getFilterByPlayerOptionsAction());
      }

      if (pageConfig.type === DEMAND_TAG_PAGE) {
        dispatch(actions.getHistoryForChartAction());
        dispatch(actions.getCountriesListAction());
        dispatch(actions.getPlatformsAction());

        if (!pageConfig.isCreatingNew) {
          dispatch(actions.getDemandTagPricingAction(DEMAND_TAG_PRICING_TYPE.price));
          dispatch(actions.getDemandTagPricingAction(DEMAND_TAG_PRICING_TYPE.adServing));
          dispatch(actions.getDemandTagPricingAction(DEMAND_TAG_PRICING_TYPE.fee));
          dispatch(actions.getDemandTagPricingAction(DEMAND_TAG_PRICING_TYPE.adRequest));
        }
      }

      if (pageConfig.type === SUPPLY_TAG_PAGE) {
        dispatch(actions.getHistoryForChartAction());
      }
    }
  }, [pageConfig?.type, pageConfig?.id, pageConfig?.isCreatingNew, pageConfig?.isDuplicate]);

  // initialize demand tag form
  useEffect(() => {
    if (pageConfig && pageConfig.type === DEMAND_TAG_PAGE) {
      dispatch(actions.initializeDemandFormDataAction());
    }
  }, [info, targeting.countriesList]);

  // initialize advertiser form
  useEffect(() => {
    if (pageConfig && pageConfig.type === DEMAND_ADVERTISER_PAGE) {
      dispatch(actions.initializeAdvertiserFormDataAction());
    }
  }, [info, targeting.countriesList]);

  // initialize supply tag form
  useEffect(() => {
    if (pageConfig && pageConfig.type === SUPPLY_TAG_PAGE) {
      dispatch(actions.initializeSupplyFormDataAction());
    }
  }, [info]);

  // set query for breadcrumbs
  useEffect(() => {
    if (info && pageConfig.getNewLink) {
      const link = pageConfig.getNewLink(info);

      if (link) {
        router.replace(link);
      }
    }
  }, [info]);

  useEffect(() => {
    if (pageConfig?.breadcrumbs) {
      dispatch(actions.setFieldAction({ pageConfig }));
    }
  }, [pageConfig?.breadcrumbs]);

  useEffect(() => {
    if (activeTabIndex === 0) {
      if (PAGES_WITH_REFRESH_TABLES.includes(pageConfig.type)) {
        resetRefreshInterval();
      }

      if (pageConfig && pageConfig.type === DEMAND_ADVERTISER_PAGE) {
        dispatch(actions.getDataAction({ type: pageConfig.type }));
      }
    } else {
      stopRefreshInterval();
    }
  }, [activeTabIndex]);

  useEffect(
    () => () => {
      dispatch(actions.setDefaultConfigAction({}));
    },
    [],
  );

  const handleCopyID = () => {
    copyToClipboard(pageConfig?.id).then(() => {
      dispatch(
        showNotificationAction({
          type: TYPE_SUCCESS,
          message: 'ID was copied to clipboard',
        }),
      );
    });
  };

  return (
    pageConfig && (
      <div className={styles.Account}>
        <Header />
        <Grid container alignItems="center" justifyContent="center" className={styles.Header}>
          <Stack
            fullWidth
            direction="row"
            justifyContent="flex-start"
            alignItems="center"
            className={styles.Breadcrumbs}
          >
            <Breadcrumbs breadcrumbs={pageConfig?.breadcrumbs} info={info} />

            <Stack direction="row" alignItems="center" justifyContent="flex-start">
              {pageConfig?.id === 'new' || pageConfig.isDuplicate ? (
                <span className={styles.Id}>New</span>
              ) : (
                <Tooltip
                  placement="top"
                  interactive="true"
                  leaveDelay={200}
                  title={
                    <div className={styles.Tooltip}>
                      {pageConfig?.id}
                      <IconButton onClick={handleCopyID} size="small">
                        <ContentCopyRounded />
                      </IconButton>
                    </div>
                  }
                >
                  <div className={styles.Id}>{pageConfig?.id}</div>
                </Tooltip>
              )}
              {(pageConfig.isCreatingNew || pageConfig.isDuplicate) && (
                <Typography className={styles.Name} variant="subtitle2" color="text.secondary" fontWeight={400}>
                  {pageConfig.type === SUPPLY_TAG_PAGE ? supply?.name : settings?.name}
                </Typography>
              )}

              {info && !pageConfig.isDuplicate && (
                <Typography className={styles.LastUpdate} variant="caption" color="text.secondary" fontWeight={400}>
                  {`Last Updated${
                    info.updatedBy ? ` by ${info.updatedBy}` : ''
                  }: ${dayjs(info.updated || info.created).format('DD/MM/YY hh:mm A')}`}
                </Typography>
              )}

              {pageConfig.showHistoryCSVButton && (
                <IconButton
                  onClick={() => {
                    dispatch(actions.getHistoryForCSVAction());
                  }}
                  size="small"
                >
                  <CustomCsvFilled fontSize="large" />
                </IconButton>
              )}
            </Stack>
          </Stack>
        </Grid>
        <Stack
          fullWidth
          spacing={1}
          direction="row"
          alignItems="center"
          justifyContent="space-between"
          className={styles.SecondHeader}
        >
          <Tabs
            className={styles.Tabs}
            value={activeTabIndex}
            onChange={(event, value) => dispatch(actions.setActiveTabIndexAction(value))}
          >
            {tabs.map((tab) => (
              <Tab
                color={tab.label === BUDGETING && info?.budgetAlarm ? 'error' : undefined}
                data-id={tab.dataId}
                key={tab.dataId}
                icon={
                  tab.label === BUDGETING &&
                  info?.budgetAlarm && (
                    <Tooltip title="This demand tag cannot serve because it has reached its allowed budget">
                      <InfoOutlined fontSize="small" htmlColor="info.main" />
                    </Tooltip>
                  )
                }
                iconPosition="end"
                label={tab.label}
                disabled={(pageConfig.isCreatingNew || pageConfig.isDuplicate) && tab.dataId === 'main'}
              />
            ))}
          </Tabs>
          {activeTabIndex === 0 && (
            <div className={styles.Filters}>
              {pageConfig?.showPlayerFilter && (
                <FormControl variant="outlined" size="small" className={styles.SelectControl}>
                  <Autocomplete
                    size="small"
                    options={[{ label: 'All Players', value: null }, ...filterByPlayerOptions]}
                    value={filterByPlayer}
                    onChange={(event, player) => dispatch(actions.setFilterByPlayerAction(player))}
                    onOpen={() => dispatch(actions.getFilterByPlayerOptionsAction())}
                    disableClearable
                    renderInput={(params) => (
                      <TextField
                        {...params}
                        placeholder="Select Player"
                        onChange={(e) => {
                          dispatch(actions.getFilterByPlayerOptionsAction({ searchText: e.target.value }));
                        }}
                      />
                    )}
                  />
                </FormControl>
              )}

              {pageConfig?.showCountriesFilter && (
                <FormControl variant="outlined" size="small" className={styles.SelectControl}>
                  <Select
                    variant="outlined"
                    size="small"
                    id="countries-filter"
                    value={filterByCountry}
                    onChange={(event) => {
                      dispatch(actions.setFilterByCountryAction(event.target.value));
                    }}
                    // eslint-disable-next-line react/prop-types
                    onOpen={props.stopRefreshInterval}
                    // eslint-disable-next-line react/prop-types
                    onClose={props.resetRefreshInterval}
                    displayEmpty
                    inputProps={{ 'aria-label': 'Without label' }}
                  >
                    <MenuItem value={null}>All Countries</MenuItem>
                    {[
                      {
                        value: 'US',
                        label: 'US Only',
                      },
                      {
                        value: 'NON_US',
                        label: 'Non-US',
                      },
                    ].map((item) => (
                      <MenuItem key={item.value} value={item.value}>
                        {item.label}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              )}

              {pageConfig?.showDevicesFilter && (
                <FormControl variant="outlined" size="small" className={styles.SelectControl}>
                  <Select
                    variant="outlined"
                    size="small"
                    id="devices-filter"
                    value={filterByDevice}
                    onChange={(event) => {
                      dispatch(actions.setFilterByDeviceAction(event.target.value));
                    }}
                    // eslint-disable-next-line react/prop-types
                    onOpen={props.stopRefreshInterval}
                    // eslint-disable-next-line react/prop-types
                    onClose={props.resetRefreshInterval}
                    displayEmpty
                    inputProps={{ 'aria-label': 'Without label' }}
                  >
                    <MenuItem value={null}>All Devices</MenuItem>
                    {[
                      {
                        value: 'DESKTOP',
                        label: 'Desktop',
                      },
                      {
                        value: 'MOBILE',
                        label: 'Mobile',
                      },
                    ].map((item) => (
                      <MenuItem key={item.value} value={item.value}>
                        {item.label}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              )}

              <DateSelect
                filterDate={filterByDate}
                setFilterDate={setFilterByDate}
                options={isAdminMP ? FILTERS : FILTERS_SELF_SERVE}
                stopRefreshInterval={stopRefreshInterval}
                resetRefreshInterval={resetRefreshInterval}
                enableCustomPeriod
              />
            </div>
          )}

          {activeTabIndex !== 0 && (
            <Stack spacing={2} direction="row" alignItems="center">
              {!pageConfig?.isCreatingNew && !pageConfig?.disableDuplicate && (
                <>
                  <Button
                    variant="text"
                    size="small"
                    color="neutral"
                    disabled={pageConfig.isDuplicate}
                    onClick={() => {
                      if (info) {
                        router.push(pageConfig.getNewLink(info, true));
                      }
                    }}
                    startIcon={<ContentCopyRounded />}
                  >
                    Duplicate
                  </Button>
                  <Divider orientation="vertical" flexItem />
                </>
              )}
              <Button
                size="small"
                onClick={() => {
                  if (pageConfig?.cancelAction) {
                    pageConfig.cancelAction(info);
                  }
                  dispatch(actions.setActiveTabIndexAction(0));
                }}
                variant="outlined"
                data-id="cancelButton"
              >
                Cancel
              </Button>
              <Button
                size="small"
                variant="contained"
                color="primary"
                data-id="saveButton"
                onClick={handleSubmitForm}
                disabled={isFormSubmitDisabled}
              >
                {pageConfig?.isCreatingNew || pageConfig?.isDuplicate ? 'Save' : 'Update'}
              </Button>
            </Stack>
          )}
        </Stack>
        {tabs.map((tabInfo, index) => (
          <TabContent
            className={classNames(styles.TabContent, CUSTOM_PARENT_STICKY_CLASS_NAME)}
            selectedId={activeTabIndex}
            id={index}
            key={tabInfo.dataId}
          >
            {tabsContent[tabInfo.contentKey]}
          </TabContent>
        ))}

        <WaterfallModal
          modal={modal}
          onClose={closeModal}
          getDataForWaterfall={getDataForWaterfall}
          getAccountsForWaterfall={getAccountsForWaterfall}
          getLabelsForWaterfall={getLabelsForWaterfall}
          setModalInfo={setModalInfo}
          bulkCreateWaterfall={bulkCreateWaterfall}
          isAdminMP={isAdminMP}
        />

        <ChangeTierModal modal={modal} onClose={closeModal} onSave={updateTiers} />

        <ChangeAdFeeModal modal={modal} onClose={closeModal} onSave={bulkUpdateDemandTag} />

        <ChangeViewabilityThresholdModal modal={modal} onClose={closeModal} onSave={bulkUpdateViewabilityThreshold} />

        <ChangeRevShareModal modal={modal} onClose={closeModal} onSave={bulkUpdateSupplyTag} />
        <ChangeExpensesModal modal={modal} onClose={closeModal} onSave={bulkUpdateSupplyTag} />

        <ConfirmFrequencyCapModal modal={modal} onClose={closeModal} onSave={updateDemandTag} />
      </div>
    )
  );
}
