import React, { Fragment, useState } from 'react';
import PropTypes from 'prop-types';
import Image from 'next/image';
import { CartesianGrid, Line, LineChart, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
import { alpha } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import {
  AccessTimeRounded,
  HistoryToggleOffRounded,
  InfoOutlined,
  PeopleOutlineRounded,
  TripOriginOutlined,
} from '@mui/icons-material';

import { ALPHA_400, ALPHA_500 } from '@/mui/constants/opacity';

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

import CustomActiveDot from './CustomActiveDot';
import CustomCursor from './CustomCursor';
import CustomDot from './CustomDot';
import CustomTick from './CustomTick';
import CustomTooltip from './CustomTooltip';
import { Chip, 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 icons = {
    users: PeopleOutlineRounded,
    totalMinutes: AccessTimeRounded,
    averageMinutes: HistoryToggleOffRounded,
  };

  const [inFocus, setInFocus] = useState(false);
  const [activeCoordinate, setActiveCoordinate] = useState(null);

  const xTicks = props.chartData.reduce((acc, item) => {
    if (item.data?.length) {
      const ticksToShow = item.data.filter((point) => point.showDot).map((point) => point.time);

      return [...acc, ...ticksToShow];
    }
    return acc;
  }, []);

  const TabIcon = icons[props.activeTab.key];

  return (
    <div className={styles.Chart}>
      <div className={styles.Info}>
        <div>
          {props.chartData.map((item, index) => (
            <Chip
              key={`${item.name}-${+index}`}
              className={styles.Chip}
              size="small"
              color={theme.palette['-graph'][index % 10]}
              shape="circular"
              label={item.name}
              variant="filled"
              icon={<TripOriginOutlined />}
            />
          ))}
        </div>

        <div className={styles.Control}>
          <div className={styles.SwitchWrap}>
            <Typography variant="subtitle2" color={inFocus ? 'primary.main' : 'text.disabled'} component="span">
              In Focus
            </Typography>

            <Switch
              className={styles.Switch}
              color="primary"
              size="small"
              onChange={() => {
                setInFocus(!inFocus);
              }}
            />

            <MaterialTooltip
              title="A second line chart that displays the selected value only for players opened in an active browser tab"
              placement="top"
            >
              <span>
                <InfoOutlined fontSize="xSmall" htmlColor="info.main" className={styles.InfoIcon} />
              </span>
            </MaterialTooltip>
          </div>
          <div className={styles.ChartIcon}>
            <TabIcon fontSize="xSmall" htmlColor="text.secondary" className={styles.InfoIcon} />
          </div>
        </div>
      </div>
      <div className={styles.ChartContent}>
        <ResponsiveContainer width="99%" height="99%">
          <LineChart
            data={props.chartData}
            margin={{
              top: 5,
              right: 10,
              left: 30,
              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 strokeDasharray="3 3" horizontal={false} strokeOpacity={0} fill="url(#areaGradient)" />

            <XAxis
              dataKey="time"
              type="category"
              allowDuplicatedCategory={false}
              interval="preserveStartEnd" // for showoing ticks always interval={0}
              tickLine={false}
              stroke={theme.palette.divider}
              ticks={xTicks}
              tick={props.chartData?.length ? <CustomTick /> : false}
            />

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

            <Tooltip
              content={
                <CustomTooltip title={props.activeTab.title} formatter={props.activeTab.chartTooltipFormatter} />
              }
              cursor={<CustomCursor activeCoordinate={activeCoordinate} />}
            />

            {props.chartData.map((item, index) => {
              const isLastDataItem = index === props.chartData.length - 1;
              const references = item.data.filter(
                (i, k) => i.showDot && !(isLastDataItem && k === item.data.length - 1),
              );

              return (
                <Fragment key={item.name}>
                  {/* line order is important for cursor component(lines to axis) */}
                  {inFocus && (
                    <Line
                      type="monotone"
                      dataKey="valueInFocus"
                      data={item.data}
                      name={`${item.name}-focus`}
                      key={`${item.name}-focus`}
                      stroke={alpha(theme.palette['-graph'][index % 10], ALPHA_500)}
                      dot={<CustomDot alwaysHide />}
                      activeDot={<CustomActiveDot setActiveCoordinate={setActiveCoordinate} />}
                    />
                  )}

                  <Line
                    type="monotone"
                    dataKey="value"
                    data={item.data}
                    name={item.name}
                    key={`${item.name}-${+index}`}
                    stroke={theme.palette['-graph'][index % 10]}
                    dot={<CustomDot />}
                    activeDot={<CustomActiveDot setActiveCoordinate={setActiveCoordinate} />}
                  />

                  {references.map((ref) => (
                    <ReferenceLine
                      key={`${item.name}-ReferenceLine-${ref.time}`}
                      x={ref.time}
                      stroke={theme.palette.divider}
                      strokeDasharray="3 3"
                    />
                  ))}
                </Fragment>
              );
            })}
          </LineChart>
        </ResponsiveContainer>
      </div>

      {!props.chartData?.length && (
        <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}>
            No Data...
          </Typography>

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

Chart.propTypes = {
  chartData: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.string.isRequired,
      name: PropTypes.string.isRequired,
      data: PropTypes.arrayOf(
        PropTypes.shape({
          time: PropTypes.number.isRequired,
          value: PropTypes.number.isRequired,
          valueInFocus: PropTypes.number.isRequired,
        }),
      ),
    }),
  ).isRequired,
  activeTab: PropTypes.shape({
    id: PropTypes.string,
    title: PropTypes.string,
    key: PropTypes.string,
    query: PropTypes.string,
    tooltipTitle: PropTypes.string,
    chartTooltipFormatter: PropTypes.func,
  }).isRequired,
};

export default Chart;
