/* eslint-disable react/prop-types */
import React from 'react';
import PropTypes from 'prop-types';
import Image from 'next/image';
import { Bar, CartesianGrid, ComposedChart, Line, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
import { alpha } from '@mui/material';
import { useTheme } from '@mui/material/styles';

import { AD_FORMATS, CALENDAR_FILTER_VALUE } from '../../constants';
import { ALPHA_400, ALPHA_600 } from '@/mui/constants/opacity';

import { abbreviateNumber } from '@/modules/@common/helpers/number';

import CustomTick from './CustomTick';
import CustomTooltip from './CustomTooltip';
import { Chip, FormControlLabel, Paper, Switch, Tooltip as MaterialTooltip, Typography } from '@/mui/components';

import img from '@/modules/analytics/common/components/Stub/img/imgNoData.png';

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

function Chart(props) {
  const theme = useTheme();
  const colors = [theme.palette.complimentary.dark, theme.palette['-graph'][10], theme.palette['-graph'][11]];

  const filtersValues = [
    {
      label: 'Ad Format',
      value: props.adFormat && AD_FORMATS.find((item) => item.value === props.adFormat)?.label,
    },
    {
      label: 'Period',
      value:
        props.calendar === CALENDAR_FILTER_VALUE.custom
          ? `${props.calendarCustom.dateStart} — ${props.calendarCustom.dateEnd}`
          : props.calendar.label,
    },
    {
      label: 'Demand Source',
      value: props.demandSources?.length ? props.demandSources.map((item) => item.label).join(', ') : null,
    },
    {
      label: 'Players',
      value: props.players?.length ? props.players.map((item) => item.label).join(', ') : null,
    },
    {
      label: 'Domain',
      value: props.domains?.length ? props.domains.map((item) => item.label).join(', ') : null,
    },
    {
      label: 'Country',
      value: props.countries?.length ? props.countries.map((item) => item.label).join(', ') : null,
    },
    {
      label: 'Device',
      value: props.devices?.length ? props.devices.map((item) => item.label).join(', ') : null,
    },
  ]
    .filter(({ value }) => !!value)
    .map((item) => `${item.label}: ${item.value}`);

  const showData = !props.isNoData && !!props.chartData?.length;

  return (
    <Paper elevation={7} className={styles.Chart}>
      {showData && (
        <>
          <div className={styles.Info}>
            <MaterialTooltip
              title={<span>{filtersValues.flatMap((element, i) => [element, <br key={i} />])}</span>}
              placement="top"
            >
              <Typography variant="body2" color="text.primary" component="span" className={styles.FiltersValues}>
                {filtersValues.join('; ')}
              </Typography>
            </MaterialTooltip>

            {props.activeCardFilter.id === 'Revenue' && (
              <FormControlLabel
                control={
                  <Switch
                    edge="end"
                    color="primary"
                    size="small"
                    checked={props.showFees}
                    onChange={props.handleShowFees}
                  />
                }
                label="Show platform fees"
                labelPlacement="start"
                slotProps={{
                  typography: {
                    variant: 'caption',
                  },
                }}
              />
            )}
          </div>
          <div className={styles.Chips}>
            {props.chartData.map((item, index) => (
              <Chip
                key={`${item.name}-${+index}`}
                className={styles.Chip}
                size="small"
                color={colors[index % 3]}
                shape="circular"
                label={item.chip}
                variant="filled"
              />
            ))}
          </div>

          <div className={styles.ChartContent}>
            <ResponsiveContainer width="99%" height="99%">
              <ComposedChart
                data={props.chartData}
                margin={{
                  top: 10,
                  right: 10,
                  left: props.showFees ? 0 : 20,
                  bottom: 5,
                }}
              >
                <defs>
                  <linearGradient id="areaGradient" gradientTransform="rotate(90)">
                    <stop offset="15.36%" stopColor={alpha(theme.palette.gradient[0], 0)} />
                    <stop offset="85%" stopColor={alpha(theme.palette.gradient[0], ALPHA_400)} />
                  </linearGradient>
                </defs>

                <CartesianGrid horizontal={false} vertical={false} fill="url(#areaGradient)" />

                <XAxis
                  dataKey="xTick"
                  type="category"
                  allowDuplicatedCategory={false}
                  interval={0}
                  tickLine={false}
                  stroke={theme.palette.divider}
                  strokeDasharray="3 3"
                  tick={props.chartData?.length ? <CustomTick /> : false}
                />

                {props.showFees && (
                  <YAxis
                    yAxisId="left"
                    orientation="left"
                    tickLine={false}
                    tick={{
                      fill: theme.palette.text.secondary,
                      fontSize: theme.typography.captionSmall.fontSize,
                      fontWeight: theme.typography.fontWeightMedium,
                    }}
                    tickFormatter={(tick) => {
                      if (tick < 1000) {
                        if (props.activeCardFilter.postfix) {
                          return Math.round(tick * 10000) / 100;
                        }
                        return Math.round(tick * 100) / 100;
                      }
                      return abbreviateNumber(tick);
                    }}
                    stroke={theme.palette.divider}
                    strokeDasharray="3 3"
                  />
                )}

                <YAxis
                  yAxisId="right"
                  orientation="right"
                  tickLine={false}
                  tick={{
                    fill: theme.palette.text.secondary,
                    fontSize: theme.typography.captionSmall.fontSize,
                    fontWeight: theme.typography.fontWeightMedium,
                  }}
                  tickFormatter={(tick) => {
                    if (tick < 1000) {
                      if (props.activeCardFilter.postfix) {
                        return Math.round(tick * 10000) / 100;
                      }
                      return Math.round(tick * 100) / 100;
                    }
                    return abbreviateNumber(tick);
                  }}
                  stroke={theme.palette.divider}
                  strokeDasharray="3 3"
                />

                <Tooltip
                  content={
                    <CustomTooltip
                      activeCardFilter={props.activeCardFilter}
                      calendar={props.calendar}
                      calendarCustom={props.calendarCustom}
                      showFees={props.showFees && props.activeCardFilter.id === 'Revenue'}
                    />
                  }
                  cursor={false}
                />

                {props.chartData.map((item, index) => (
                  <Line
                    yAxisId="right"
                    type="monotone"
                    dataKey={props.activeCardFilter.key}
                    data={item.buckets}
                    name={item.name}
                    key={`${item.name}-${+index}`}
                    stroke={colors[index % 3]}
                    strokeWidth={2}
                  />
                ))}

                {props.showFees &&
                  props.chartData.map((item, index) => (
                    <Bar
                      yAxisId="left"
                      dataKey="platformFee"
                      data={item.buckets}
                      name={item.name}
                      fill={alpha(colors[index % 3], ALPHA_600)}
                      key={`${item.name}-bar-${+index}`}
                      barSize={5}
                      minPointSize={3}
                    />
                  ))}
              </ComposedChart>
            </ResponsiveContainer>
          </div>
        </>
      )}

      {!showData && (
        <div className={styles.NoData}>
          <div className={styles.NoDataImageWrapper}>
            <Image src={img} fill unoptimized loading="eager" alt="No Data" />
          </div>

          <Typography variant="subtitle1" color="text.secondary" className={styles.NoDataTitle}>
            {props.isChartDataLoading || props.isTotalsLoading ? 'Loading...' : 'No Data...'}
          </Typography>

          <Typography variant="caption" color="text.disabled" component="div">
            There is not enough data to display. Please change your request.
          </Typography>
        </div>
      )}
    </Paper>
  );
}

Chart.propTypes = {
  chartData: PropTypes.arrayOf(
    PropTypes.shape({
      name: PropTypes.string.isRequired,
      buckets: PropTypes.arrayOf(
        PropTypes.shape({
          time: PropTypes.number.isRequired,
          xTick: PropTypes.number.isRequired,
          externalRevenues: PropTypes.number,
          platformFee: PropTypes.number,
          adImpressions: PropTypes.number,
          viewableImpressions: PropTypes.number,
          viewability: PropTypes.number,
          fillRate: PropTypes.number,
          adRequests: PropTypes.number,
          cpm: PropTypes.number,
          rpm: PropTypes.number,
          playerLoads: PropTypes.number,
          netRevenue: PropTypes.number,
        }),
      ),
      chip: PropTypes.string.isRequired,
    }),
  ).isRequired,
  calendar: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.shape({
      label: PropTypes.string.isRequired,
      dateRange: PropTypes.shape({
        stringFrom: PropTypes.string,
        stringTo: PropTypes.string,
        timezone: PropTypes.string,
      }),
      dateRangeComparison: PropTypes.shape({
        stringFrom: PropTypes.string,
        stringTo: PropTypes.string,
        timezone: PropTypes.string,
      }),
      ranges: PropTypes.arrayOf(
        PropTypes.shape({
          stringFrom: PropTypes.string,
          stringTo: PropTypes.string,
          timezone: PropTypes.string,
        }),
      ),
      interval: PropTypes.shape({
        unit: PropTypes.string,
        value: PropTypes.number,
      }),
      xTickFormatter: PropTypes.func,
      chipFormatter: PropTypes.func,
      chartTooltipFormatter: PropTypes.func,
    }),
  ]).isRequired,
  calendarCustom: PropTypes.shape({
    dateRange: PropTypes.shape({
      stringFrom: PropTypes.string,
      stringTo: PropTypes.string,
      timezone: PropTypes.string,
    }),
    dateRangeComparison: PropTypes.shape({
      stringFrom: PropTypes.string,
      stringTo: PropTypes.string,
      timezone: PropTypes.string,
    }),
    ranges: PropTypes.arrayOf(
      PropTypes.shape({
        stringFrom: PropTypes.string,
        stringTo: PropTypes.string,
        timezone: PropTypes.string,
      }),
    ),
    interval: PropTypes.shape({
      unit: PropTypes.string,
      value: PropTypes.number,
    }),
    xTickFormatter: PropTypes.func,
    chipFormatter: PropTypes.func,
    chartTooltipFormatter: PropTypes.func,
  }).isRequired,

  activeCardFilter: PropTypes.shape({
    title: PropTypes.string.isRequired,
    id: PropTypes.string.isRequired,
    key: PropTypes.string.isRequired,
    prefix: PropTypes.string,
    postfix: PropTypes.string,
  }).isRequired,

  countries: PropTypes.arrayOf(
    PropTypes.shape({
      label: PropTypes.string.isRequired,
      value: PropTypes.number.isRequired,
    }),
  ).isRequired,

  demandSources: PropTypes.arrayOf(
    PropTypes.shape({
      label: PropTypes.string.isRequired,
      value: PropTypes.number.isRequired,
    }),
  ).isRequired,

  domains: PropTypes.arrayOf(
    PropTypes.shape({
      label: PropTypes.string.isRequired,
      value: PropTypes.number.isRequired,
    }),
  ).isRequired,

  devices: PropTypes.arrayOf(
    PropTypes.shape({
      label: PropTypes.string.isRequired,
      value: PropTypes.number.isRequired,
    }),
  ).isRequired,

  players: PropTypes.arrayOf(
    PropTypes.shape({
      label: PropTypes.string.isRequired,
      value: PropTypes.string.isRequired,
    }),
  ).isRequired,

  showFees: PropTypes.bool.isRequired,
  isNoData: PropTypes.bool.isRequired,
  isChartDataLoading: PropTypes.bool.isRequired,
  isTotalsLoading: PropTypes.bool.isRequired,
  handleShowFees: PropTypes.func.isRequired,
};

export default Chart;
