import PropTypes from "prop-types";
import React from "react";
import ReactHighcharts from "react-highcharts";
import { blueLight, teal } from "@bufferapp/ui/style/colors";
import chartConfig from "./chartConfig";
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import dayTimezone from 'dayjs/plugin/timezone';

dayjs.extend(utc);
dayjs.extend(dayTimezone);

const chartFillColorBlue = blueLight;
const paidFill = teal;

function prepareSeries(dailyMetric) {
  const organicSeries = Array.from(dailyMetric, (day) => {
    const dayStartTimestamp = dayjs
      .utc(Number(day.day))
      .startOf("day")
      .valueOf();

    return {
      x: dayStartTimestamp,
      y: day.metric ? day.metric.value : 0,
      label: day.metric ? day.metric.label : "",
      metricKey: day.metric ? day.metric.metricKey : "",
      currency: day.metric ? day.metric.currency : "",
      valueFirst: day.metric ? day.metric.valueFirst : false,
      color: chartFillColorBlue,
      states: {
        hover: {
          color: chartFillColorBlue,
          brightness: 0.0,
        },
      },
    };
  });

  const paidSeries = Array.from(dailyMetric, (day) => {
    const dayStartTimestamp = dayjs
      .utc(Number(day.day))
      .startOf("day")
      .valueOf();

    return {
      x: dayStartTimestamp,
      y: day.metric ? day.metric.paid : 0,
      label: day.metric ? day.metric.label : "",
      metricKey: day.metric ? day.metric.metricKey : "",
      color: paidFill,
      states: {
        hover: {
          color: paidFill,
          brightness: 0.0,
        },
      },
    };
  });

  return [{ data: organicSeries }, { data: paidSeries }];
}

function preparePlotOptions(dailyMetric) {
  const areasplineOptions = {
    marker: {
      enabled: false,
      lineWidth: 3,
      radius: 4,
      symbol: "circle",
      lineColor: chartFillColorBlue,
      fillColor: ReactHighcharts.Highcharts.Color(chartFillColorBlue)
        .brighten(0.1)
        .get("rgba"),
    },
    states: {
      hover: {
        radiusPlus: 1.5,
      },
    },
    lineColor: chartFillColorBlue,
    fillColor: chartFillColorBlue,
  };

  let options = {};
  if (dailyMetric.length <= 15) {
    options = {
      column: {
        pointPlacement: "between",
        pointWidth: null,
        pointPadding: 0.2,
        borderWidth: 1,
        groupPadding: null,
        stacking: "normal",
      },
      areaspline: areasplineOptions,
      series: {
        cursor: "pointer",
      },
    };
  } else if (dailyMetric.length > 15 && dailyMetric.length <= 80) {
    options = {
      column: {
        pointPlacement: "between",
        pointWidth: null,
        pointPadding: null,
        borderWidth: 1,
        groupPadding: null,
        stacking: "normal",
      },
      areaspline: areasplineOptions,
      series: {
        cursor: "pointer",
      },
    };
  } else if (dailyMetric.length > 80) {
    options = {
      column: {
        pointPlacement: "on",
        pointWidth: null,
        pointPadding: 0,
        borderWidth: 0,
        groupPadding: 0,
        stacking: "normal",
      },
      areaspline: areasplineOptions,
      series: {
        cursor: "pointer",
      },
    };
  }
  return options;
}

function sortValues(a, b) {
  return a - b;
}

function addMaxMinToYAxis(dailyMetric) {
  const valuesOrganic = [];
  const valuesPaid = [];
  dailyMetric.map((item) => {
    valuesOrganic.push(item.metric.value);
    if (item.metric.paid > 0) {
      valuesPaid.push(item.metric.paid);
    }
  });
  const sortedOrganic = valuesOrganic.sort(sortValues);
  const sortedPaid = valuesPaid.length > 0 ? valuesPaid.sort(sortValues) : [0];

  const yAxisWithMaxMin = {
    title: { text: null },
    gridLineWidth: 0,
    lineWidth: 0,
    tickWidth: 0,
    labels: {
      enabled: false,
    },
    max:
      !valuesPaid || !valuesPaid.length
        ? sortedOrganic[sortedOrganic.length - 1]
        : sortedOrganic[sortedOrganic.length - 1] +
          sortedPaid[sortedPaid.length - 1],
    min:
      !valuesPaid || !valuesPaid.length
        ? sortedOrganic[0]
        : [sortedOrganic[0], sortedPaid[0]].sort(sortValues)[0],
  };

  return yAxisWithMaxMin;
}

function prepareChartOptions(dailyMetric, chartType, chartSize, controlMinMax) {
  const config = Object.assign({}, chartConfig(chartType, chartSize));
  config.plotOptions = preparePlotOptions(dailyMetric);
  const sortedDailyMetric = dailyMetric.sort(
    (a, b) => parseInt(a.day) - parseInt(b.day)
  );
  config.series = prepareSeries(sortedDailyMetric);

  if (controlMinMax) {
    config.yAxis = addMaxMinToYAxis(dailyMetric);
  }
  return config;
}

const GridItemChart = ({ dailyData, chartType, chartSize, controlMinMax }) => {
  const charOptions = prepareChartOptions(dailyData, chartType, chartSize, controlMinMax);
  return <ReactHighcharts config={charOptions} />;
};

GridItemChart.propTypes = {
  dailyData: PropTypes.arrayOf(
    PropTypes.shape({
      day: PropTypes.string,
      metric: PropTypes.shape({
        diff: PropTypes.number,
        label: PropTypes.string,
        value: PropTypes.number,
      }),
    })
  ).isRequired,
  chartType: PropTypes.oneOf(["column", "areaspline"]).isRequired,
  chartSize: PropTypes.oneOf(["small", "default"]),
  controlMinMax: PropTypes.bool,
};

GridItemChart.defaultProps = {
  chartSize: "default",
}

export default GridItemChart;
