import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import classNames from 'clsx';
import dayjs from 'dayjs';
import timezonePlugin from 'dayjs/plugin/timezone';
import utcPlugin from 'dayjs/plugin/utc';

import {
  AD_FORMAT_COLLECTION,
  CALENDAR_FILTER_COLLECTION,
  CALENDAR_FILTER_CUSTOM,
  CALENDAR_FILTER_THIS_MONTH,
  DEVICE_COLLECTION,
} from '@/modules/analytics/monetization/constants';

import type { DataRecordType, StateFiltersType, StateTableSliceType } from '../types';

import { getConfigHeaders, getConfigSubHeaders } from '../helpers';
import * as computedState from '../helpers/computedState';
import * as selectors from '../redux/selectors';
import {
  exportToCsvAction,
  getCountriesAction,
  getCountriesFullListAction,
  getDataAction,
  getDemandSourcesAction,
  getDomainsAction,
  getPlayersAction,
  setAction,
  setTableAction,
} from '../redux/slices';
import { getUserTimezoneSelector } from '@/modules/@common/user/redux/selectors';
import { omitUndefinedProps } from '@/mui/helpers';

import CommonList from '@/modules/@common/List';
import MultiAutocomplete from '@/modules/@common/MultiAutocomplete/MultiAutocomplete';
import CommonTable from '@/modules/@common/Table';
import { DialogCalendarRange } from '@/modules/analytics/common/components';
import SpecialPopper from '@/modules/analytics/monetization/components/Filters/components/SpecialPopper';
import Empty from './Empty/Empty';
import {
  FormControl,
  IconButton,
  InputLabel,
  MenuItem,
  Select,
  Stack,
  TableCell,
  TableRow,
  TextField,
  Tooltip,
} from '@/mui/components';
import { CustomCsvFilled } from '@/mui/components/CustomIcon';

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

type StateFlattenType = StateTableSliceType & StateFiltersType;

dayjs.extend(utcPlugin);
dayjs.extend(timezonePlugin);

function List() {
  const dispatch = useDispatch();
  const userTimezone = useSelector(getUserTimezoneSelector);
  const data = useSelector(selectors.dataSelector);
  const page = useSelector(selectors.pageSelector);
  const pageSize = useSelector(selectors.pageSizeSelector);
  const totalCount = useSelector(selectors.totalCountSelector);
  const sortBy = useSelector(selectors.sortBySelector);
  const sortOrder = useSelector(selectors.sortOrderSelector);
  const adFormat = useSelector(selectors.adFormatSelector);
  const period = useSelector(selectors.periodSelector);
  const customDateFrom = useSelector(selectors.customDateFromSelector);
  const customDateTo = useSelector(selectors.customDateToSelector);

  const devices = useSelector(selectors.devicesSelector);

  const demandSources = useSelector(selectors.demandSourcesSelector);
  const demandSourcesOptions = useSelector(selectors.demandSourcesOptionsSelector);

  const players = useSelector(selectors.playersSelector);
  const playersOptions = useSelector(selectors.playersOptionsSelector);

  const countries = useSelector(selectors.countriesSelector);
  const countriesOptions = useSelector(selectors.countriesOptionsSelector);

  const domains = useSelector(selectors.domainsSelector);
  const domainsOptions = useSelector(selectors.domainsOptionsSelector);

  const shouldShowEmpty = useSelector(computedState.shouldShowEmpty);
  const [customDateRangePicker, toggleCustomDateRangePicker] = useState(false);

  const handleFilter = (filter: Partial<StateFlattenType>, withoutRequest = false) => {
    const { sortBy: sortBy$, sortOrder: sortOrder$, page: page$, pageSize: pageSize$, ...mainState } = filter;

    const res = omitUndefinedProps({
      sortBy: sortBy$,
      sortOrder: sortOrder$,
      page: page$,
      pageSize: pageSize$,
      selected: [],
    });

    dispatch(setTableAction(res));

    dispatch(setAction({ ...mainState }));

    if (!withoutRequest) {
      dispatch(getDataAction());
    }
  };

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

  const toLocaleMoneyString = (value?: number) =>
    typeof value === 'number'
      ? `$${value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
      : '';

  return (
    <>
      <CommonList
        title="Revenue Overview"
        renderFilters={
          <Stack direction="row" alignItems="center" spacing={2} fullWidth>
            <FormControl fullWidth className={classNames(styles.Filter, styles.Filter___fixed)}>
              <InputLabel>Ad Format</InputLabel>
              <Select
                size="small"
                label="Ad Format"
                value={adFormat}
                data-id="adFormat"
                variant="outlined"
                displayEmpty
                onChange={(event) =>
                  handleFilter({ adFormat: event.target.value as StateFiltersType['adFormat'], page: 1 })
                }
              >
                {AD_FORMAT_COLLECTION.map((format) => (
                  <MenuItem key={format.value} value={format.value}>
                    {format.label}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>

            <FormControl fullWidth className={classNames(styles.Filter, styles.Filter___fixed)}>
              <InputLabel>Period</InputLabel>
              <Select
                size="small"
                label="Period"
                value={period}
                renderValue={
                  period === CALENDAR_FILTER_CUSTOM && customDateFrom && customDateTo
                    ? () => `${dayjs(customDateFrom).format('MMM DD YY')} - ${dayjs(customDateTo).format('MMM DD YY')}`
                    : undefined
                }
                data-id="period"
                variant="outlined"
                onChange={(event) => {
                  const newPeriod = event.target.value as StateFiltersType['period'];

                  handleFilter({ period: newPeriod, page: 1 }, newPeriod === CALENDAR_FILTER_CUSTOM);
                }}
              >
                {CALENDAR_FILTER_COLLECTION.map((item) => (
                  <MenuItem
                    key={item.value}
                    value={item.value}
                    onClick={() => {
                      if (item.value === CALENDAR_FILTER_CUSTOM) {
                        toggleCustomDateRangePicker(true);
                      }
                    }}
                  >
                    {item.label}
                  </MenuItem>
                ))}
              </Select>
            </FormControl>

            <MultiAutocomplete
              data-id="demandSources"
              size="small"
              limitTags={1}
              options={demandSourcesOptions}
              value={demandSources}
              className={classNames(styles.Filter, styles.Filter___multiple)}
              onChange={(event, newValue) => {
                handleFilter({ demandSources: newValue as StateFiltersType['demandSources'], page: 1 });
              }}
              onInputChange={(event, value: string) => dispatch(getDemandSourcesAction(value))}
              onOpen={() => dispatch(getDemandSourcesAction(''))}
              renderInput={(params) => (
                <TextField {...params} placeholder="Select Demand Source" label="Demand Source" size="small" />
              )}
              slots={{
                popper: SpecialPopper,
              }}
              classes={{
                option: styles.FilterOption,
              }}
            />

            <MultiAutocomplete
              data-id="players"
              size="small"
              limitTags={1}
              options={playersOptions}
              value={players}
              className={classNames(styles.Filter, styles.Filter___multiple)}
              onChange={(event, newValue) => {
                handleFilter({ players: newValue as StateFiltersType['players'], page: 1 });
              }}
              onInputChange={(event, value: string) => dispatch(getPlayersAction(value))}
              onOpen={() => dispatch(getPlayersAction(''))}
              renderInput={(params) => (
                <TextField {...params} placeholder="Select Player" label="Player" size="small" />
              )}
              slots={{
                popper: SpecialPopper,
              }}
              classes={{
                option: styles.FilterOption,
              }}
            />

            <MultiAutocomplete
              data-id="domains"
              size="small"
              multiple
              limitTags={1}
              options={domainsOptions}
              className={classNames(styles.Filter, styles.Filter___multiple)}
              value={domains}
              onChange={(event, newValue) => {
                handleFilter({ domains: newValue as StateFiltersType['domains'], page: 1 });
              }}
              onInputChange={(event, value: string) => dispatch(getDomainsAction(value))}
              onOpen={() => dispatch(getDomainsAction(''))}
              renderInput={(params) => (
                <TextField {...params} placeholder="Select Domain" label="Domain" size="small" />
              )}
              slots={{
                popper: SpecialPopper,
              }}
              classes={{
                option: styles.FilterOption,
              }}
            />

            <MultiAutocomplete
              data-id="countries"
              size="small"
              multiple
              limitTags={1}
              className={classNames(styles.Filter, styles.Filter___multiple)}
              options={countriesOptions}
              value={countries}
              onChange={(event, newValue) => {
                handleFilter({ countries: newValue as StateFiltersType['domains'], page: 1 });
              }}
              onInputChange={(event, value: string) => dispatch(getCountriesAction(value))}
              onOpen={() => dispatch(getCountriesAction(''))}
              renderInput={(params) => (
                <TextField {...params} placeholder="Select Country" label="Country" size="small" />
              )}
              slots={{
                popper: SpecialPopper,
              }}
              classes={{
                option: styles.FilterOption,
              }}
            />

            <MultiAutocomplete
              data-id="devices"
              className={classNames(styles.Filter, styles.Filter___fixed, styles.Filter___multiple)}
              size="small"
              multiple
              limitTags={1}
              options={DEVICE_COLLECTION}
              value={devices}
              onChange={(event, newValue) => {
                handleFilter({ devices: newValue as StateFiltersType['devices'], page: 1 });
              }}
              onInputChange={() => null}
              renderInput={(params) => (
                <TextField {...params} placeholder="Select Device" label="Device" size="small" />
              )}
              slots={{
                popper: SpecialPopper,
              }}
              classes={{
                option: styles.FilterOption,
              }}
            />
          </Stack>
        }
        renderActions={
          <Tooltip title="Export to CSV">
            <IconButton disabled={shouldShowEmpty} onClick={() => dispatch(exportToCsvAction())}>
              <CustomCsvFilled />
            </IconButton>
          </Tooltip>
        }
      >
        {shouldShowEmpty ? (
          <Empty />
        ) : (
          <CommonTable
            configHeaders={getConfigHeaders()}
            configSubHeaders={getConfigSubHeaders()}
            configRenderRow={(row: DataRecordType) => (
              <TableRow key={row.customId} hover>
                <TableCell>
                  <div
                    className={classNames(styles.Cell, {
                      [styles.Cell___total]: row.customId === -1,
                    })}
                  >
                    {row.time ? dayjs(row.time).tz(userTimezone).format('MMM D, YYYY hh:mm A') : 'Total'}
                  </div>
                </TableCell>
                <TableCell align="right">
                  <div
                    className={classNames(styles.Cell, {
                      [styles.Cell___total]: row.customId === -1,
                    })}
                  >
                    {row.playerLoads}
                  </div>
                </TableCell>
                <TableCell align="right">
                  <div
                    className={classNames(styles.Cell, {
                      [styles.Cell___total]: row.customId === -1,
                    })}
                  >
                    {row.videoAdImpressions}
                  </div>
                </TableCell>
                <TableCell align="right">
                  <div
                    className={classNames(styles.Cell, {
                      [styles.Cell___total]: row.customId === -1,
                    })}
                  >
                    {row.displayAdImpressions}
                  </div>
                </TableCell>
                <TableCell align="right">
                  <div
                    className={classNames(styles.Cell, {
                      [styles.Cell___total]: row.customId === -1,
                    })}
                  >
                    {toLocaleMoneyString(row.publisherVideoRevenue + row.publisherDisplayRevenue)}
                  </div>
                </TableCell>
                <TableCell align="right">
                  <div
                    className={classNames(styles.Cell, {
                      [styles.Cell___total]: row.customId === -1,
                    })}
                  >
                    {toLocaleMoneyString(row.anyclipVideoRevenue + row.anyclipDisplayRevenue)}
                  </div>
                </TableCell>
                <TableCell align="right">
                  <div
                    className={classNames(styles.Cell, {
                      [styles.Cell___total]: row.customId === -1,
                    })}
                  >
                    {toLocaleMoneyString(row.platformFee)}
                  </div>
                </TableCell>
                <TableCell align="right">
                  <div
                    className={classNames(styles.Cell, {
                      [styles.Cell___total]: row.customId === -1,
                    })}
                  >
                    {toLocaleMoneyString(row.netRevenue)}
                  </div>
                </TableCell>
                <TableCell align="right">
                  <div
                    className={classNames(styles.Cell, {
                      [styles.Cell___total]: row.customId === -1,
                    })}
                  >
                    {toLocaleMoneyString(row.rpm)}
                  </div>
                </TableCell>
              </TableRow>
            )}
            data={data || []}
            sortBy={sortBy}
            sortOrder={sortOrder}
            totalCount={totalCount}
            page={page}
            rowsPerPage={pageSize}
            onFilter={handleFilter}
          />
        )}
      </CommonList>
      <DialogCalendarRange
        open={customDateRangePicker}
        onClose={() => {
          toggleCustomDateRangePicker(false);

          handleFilter({ period: CALENDAR_FILTER_THIS_MONTH, page: 1 });
        }}
        onDateSubmit={({ dateStart, dateEnd }: { dateStart: string; dateEnd: string }) => {
          toggleCustomDateRangePicker(false);

          handleFilter({
            customDateFrom: dateStart,
            customDateTo: dateEnd,
            page: 1,
          });
        }}
      />
    </>
  );
}

export default List;
