import React, { useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import dayjs from 'dayjs';
import weekOfYearPlugin from 'dayjs/plugin/weekOfYear';
import { PictureAsPdfRounded } from '@mui/icons-material';

import { AD_FORMAT_CONFIG, CALENDAR_FILTER_VALUE, CARDS_FILTERS_ALL, CARDS_FILTERS_FOR_SOURCES } from '../constants';
import { PDF_EXPORT_HIDE_CONTENT } from '@/modules/analytics/common/constants';

import * as selectors from '../redux/selectors';
import * as actions from '../redux/slices';
import { getUserTimezoneSelector } from '@/modules/@common/user/redux/selectors';

import { DialogCalendarRange, Layout } from '@/modules/analytics/common/components';
import Card from './Card';
import Chart from './Chart';
import Countries from './Countries';
import Device from './Device';
import Filters from './Filters';
import { CircularProgress, IconButton, Typography } from '@/mui/components';
import { CustomCsvFilled } from '@/mui/components/CustomIcon';

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

dayjs.extend(weekOfYearPlugin);

function MonetizationDashboard() {
  const dispatch = useDispatch();

  const userTimezone = useSelector(getUserTimezoneSelector);
  const calendar = useSelector(selectors.calendarSelector);
  const calendarCustom = useSelector(selectors.calendarCustomSelector);
  const activeCardFilter = useSelector(selectors.activeCardFilterSelector);
  const adFormat = useSelector(selectors.adFormatSelector);
  const demandSources = useSelector(selectors.demandSourcesSelector);
  const demandSourcesOptions = useSelector(selectors.demandSourcesOptionsSelector);
  const players = useSelector(selectors.playersSelector);
  const playersOptions = useSelector(selectors.playersOptionsSelector);
  const domains = useSelector(selectors.domainsSelector);
  const domainsOptions = useSelector(selectors.domainsOptionsSelector);
  const countries = useSelector(selectors.countriesSelector);
  const countriesOptions = useSelector(selectors.countriesOptionsSelector);
  const countriesFullList = useSelector(selectors.countriesFullListSelector);
  const devices = useSelector(selectors.devicesSelector);
  const totals = useSelector(selectors.totalsSelector);
  const chartData = useSelector(selectors.chartDataSelector);
  const showFees = useSelector(selectors.showFeesSelector);
  const isExportPdfLoading = useSelector(selectors.isExportPdfLoadingSelector);
  const isTotalsLoading = useSelector(selectors.isTotalsLoadingSelector);
  const isChartDataLoading = useSelector(selectors.isChartDataLoadingSelector);
  const getCountries = (o) => dispatch(actions.getCountriesAction(o));
  const getDemandSources = (o) => dispatch(actions.getDemandSourcesAction(o));
  const getDomains = (o) => dispatch(actions.getDomainsAction(o));
  const getPlayers = (o) => dispatch(actions.getPlayersAction(o));
  const exportToCSV = (o) => dispatch(actions.exportToCSVAction(o));

  const contentRef = useRef(null);
  const [isCalendarOpen, setIsCalendarOpen] = useState(false);

  const CARDS_FILTERS =
    demandSources?.length && adFormat !== AD_FORMAT_CONFIG.sponsored.value
      ? CARDS_FILTERS_FOR_SOURCES
      : CARDS_FILTERS_ALL;

  const handleExportToPDF = () => dispatch(actions.exportToPDFAction(contentRef.current));

  const activeCard = {
    ...activeCardFilter,
    ...(activeCardFilter?.getCardConfig
      ? activeCardFilter.getCardConfig({
          demandSources: demandSources ?? [],
          adFormat,
        })
      : {}),
  };

  const getData = () => {
    dispatch(actions.getTotalsAction());
    dispatch(actions.getChartDataAction());
  };

  useEffect(() => {
    dispatch(actions.getCountriesFullListAction());
    dispatch(actions.getDemandSourcesAction());
    dispatch(actions.getDomainsAction());
    dispatch(actions.getPlayersAction());
  }, []);

  useEffect(() => {
    getData();
  }, [countriesFullList]);

  const resetFilters = () => {
    dispatch(actions.setDefaultStateAction());

    dispatch(actions.getCountriesFullListAction());
    dispatch(actions.getDemandSourcesAction());
    dispatch(actions.getDomainsAction());
    dispatch(actions.getPlayersAction());

    getData();
  };

  const handleFilterSetCalendar = (calendarFilter) => {
    dispatch(
      actions.setFieldAction({
        calendar: calendarFilter,
      }),
    );

    if (calendarFilter === CALENDAR_FILTER_VALUE.custom) {
      setIsCalendarOpen(true);
      return;
    }

    getData();
  };

  const handleMenuItemClick = (itemValue) => {
    if (itemValue === CALENDAR_FILTER_VALUE.custom) {
      setIsCalendarOpen(true);
    }
  };

  const handleFilterChange = (filterName, value, prevValue) => {
    dispatch(
      actions.setFieldAction({
        [filterName]: value,
      }),
    );

    if (
      (filterName === 'demandSources' && (value?.length === 0 || prevValue?.length === 0)) ||
      filterName === 'adFormat'
    ) {
      dispatch(
        actions.setFieldAction({
          activeCardFilter: CARDS_FILTERS[0],
        }),
      );
    }

    getData();
  };

  const handleFilterInputChange = (filterName, value) => {
    const filterSearchesFuncs = {
      countries: getCountries,
      demandSources: getDemandSources,
      domains: getDomains,
      players: getPlayers,
    };

    filterSearchesFuncs[filterName](value);
  };

  const handleShowFees = () => {
    dispatch(
      actions.setFieldAction({
        showFees: !showFees,
      }),
    );
  };

  return (
    <Layout ref={contentRef} contentClassName={styles.Layout}>
      <section className={styles.Header}>
        <Typography className={styles.Title} variant="h6Alt" color="text.primary" component="span" fontWeight={400}>
          Monetization
        </Typography>

        <div className={styles.Exports} data-pdf-export={PDF_EXPORT_HIDE_CONTENT}>
          {isExportPdfLoading && (
            <CircularProgress
              size={14}
              color="inherit"
              classes={{
                root: styles.LoadingSpinner,
              }}
            />
          )}

          {!isExportPdfLoading && (
            <IconButton onClick={handleExportToPDF}>
              <PictureAsPdfRounded />
            </IconButton>
          )}

          <IconButton onClick={exportToCSV}>
            <CustomCsvFilled />
          </IconButton>
        </div>
      </section>

      <Filters
        adFormat={adFormat}
        calendar={calendar}
        calendarCustom={calendarCustom}
        handleFilterSetCalendar={handleFilterSetCalendar}
        handleMenuItemClick={handleMenuItemClick}
        countries={countries}
        countriesOptions={countriesOptions}
        demandSources={demandSources}
        demandSourcesOptions={demandSourcesOptions}
        players={players}
        playersOptions={playersOptions}
        domains={domains}
        domainsOptions={domainsOptions}
        devices={devices}
        handleFilterChange={handleFilterChange}
        handleFilterInputChange={handleFilterInputChange}
        resetFilters={resetFilters}
      />

      <section className={styles.Cards}>
        <div className={styles.CardsFilters}>
          {CARDS_FILTERS.map((item) => {
            const cardConfig = item.getCardConfig({
              demandSources: demandSources ?? [],
              adFormat,
            });
            return (
              !cardConfig.hide && (
                <Card
                  key={item.id}
                  activeCardFilter={activeCard}
                  id={item.id}
                  title={cardConfig.title}
                  value={cardConfig.key ? totals?.total?.[cardConfig.key] : totals?.total?.[item.key]}
                  valuePct={totals?.comparisonPct?.[`${item.key}Pct`] ?? null}
                  prefix={item.prefix}
                  postfix={item.postfix}
                  hideComparisonNumbers={totals?.hideComparisonNumbers}
                  demandSources={demandSources}
                  isTotalsLoading={isTotalsLoading}
                  tooltipText={cardConfig.tooltip}
                  isDisabled={item?.disableByAdFormat ? item.disableByAdFormat(adFormat) : false}
                  onClick={() => {
                    dispatch(
                      actions.setFieldAction({
                        activeCardFilter: {
                          ...item,
                          ...cardConfig,
                        },
                        showFees: false,
                      }),
                    );
                  }}
                />
              )
            );
          })}
        </div>
        <div className={styles.Devices}>
          <Device devices={totals.devices} isTotalsLoading={isTotalsLoading} />
        </div>
        <div className={styles.Countries}>
          <Countries countries={totals?.countries ?? []} isTotalsLoading={isTotalsLoading} />
        </div>
      </section>

      <section className={styles.Chart}>
        <Chart
          chartData={chartData}
          showFees={showFees}
          activeCardFilter={activeCard}
          calendar={calendar}
          calendarCustom={calendarCustom}
          demandSources={demandSources}
          players={players}
          domains={domains}
          countries={countries}
          devices={devices}
          adFormat={adFormat}
          isNoData={totals?.total?.[activeCard.key] === null || totals?.total?.[activeCard.key] === undefined}
          handleShowFees={handleShowFees}
          isChartDataLoading={isChartDataLoading}
          isTotalsLoading={isTotalsLoading}
        />
      </section>

      <DialogCalendarRange
        open={isCalendarOpen}
        onClose={() => {
          setIsCalendarOpen(false);
          dispatch(
            actions.setFieldAction({
              calendar: CALENDAR_FILTER_VALUE.thisMonth,
            }),
          );
          getData();
        }}
        onDateSubmit={({ dateStart, dateEnd }) => {
          const timezone = userTimezone;
          const diff = dayjs(dateEnd).diff(dateStart, 'days');
          const isMoreThanOneDay = diff > 1;

          dispatch(
            actions.setFieldAction({
              calendarCustom: {
                dateStart,
                dateEnd,
                dateRange: {
                  stringFrom: dateStart,
                  stringTo: dateEnd,
                  timezone,
                },
                ranges: [
                  {
                    stringFrom: dateStart,
                    stringTo: dateEnd,
                    timezone,
                  },
                ],
                interval: {
                  unit: isMoreThanOneDay ? 'DAYS' : 'HOURS',
                  value: 1,
                },
                xTickFormatter: (value) => {
                  if (isMoreThanOneDay) {
                    return value.format('MMM DD');
                  }
                  return value.format('HH');
                },
                chipFormatter: (value) => {
                  if (isMoreThanOneDay) {
                    return `Week ${dayjs(value).week()}`;
                  }
                  return value.format('MMM DD');
                },
                chartTooltipFormatter: (value) => {
                  if (isMoreThanOneDay) {
                    return `${value.format('ddd MMM DD')}, Week ${dayjs(value).week()}`;
                  }
                  return value.format('ddd MMM DD');
                },
                chartTooltipTitleFormatter: isMoreThanOneDay ? null : (value) => `${value.format('HH')}:00`,
              },
            }),
          );

          setIsCalendarOpen(false);

          getData();
        }}
      />
    </Layout>
  );
}

export default MonetizationDashboard;
