import React, { useEffect, useState } from "react";
import { LineGraph } from "./LineGraph";
import amplitude from "amplitude-js";
import { parseDateString, sortByDate } from "../util/date";
import { colors } from "../colors";
import {
  LabelAnalysisTrackFieldsFragment,
  TrackAnalysisCategory,
  TrackAnalysisMetric,
  useLabelTrackAnalysisQuery,
  useLabelsQuery,
  LabelFieldsFragment,
  useRegionsQuery,
  MarketFieldsFragment,
} from "../graphql/__generated__/sdk";
import * as df from "date-fns";
import { ActivityIndicator } from "./ActivityIndicator";
import { formatCountShort } from "../util/util";

const metricNames: Record<TrackAnalysisMetric, string> = {
  STREAMS_TOTAL: "Streams",
  STREAMS_LEAN_FORWARD: "Lean forward streams",
};

function* decades(max: number) {
  for (let i = 10; i <= max; i *= 10) {
    yield i;
  }
}

const streamThresholds = Array.from(decades(100_000_000));

function productImageUri(productId: string) {
  return `https://qa-images-api.atlas.stream/v2/albums/by_gras_product_id/${productId.replace(
    /^(GRAS_)/,
    ""
  )}`;
}

const TrackRow: React.FC<{
  track: LabelAnalysisTrackFieldsFragment;

  maxChangePercentage: number;
}> = ({ track, maxChangePercentage }) => {
  const dates = track.metrics
    .map(({ date, streams }) => ({ date, streams }))
    .sort(sortByDate)
    .map(({ date }) => parseDateString(date));

  const data = track.metrics.map(({ date, streams }) => ({
    date,
    data: streams,
  }));

  return (
    <tr className="track-row">
      <td className="track">
        <div className="product-image-container">
          <img
            className="product"
            src={productImageUri(track.track.product.id)}
            onError={(e) => (e.currentTarget.style.opacity = "0")}
            alt={track.track.name}
          />
        </div>
      </td>
      <td>
        <span>{track.track.name}</span>
      </td>
      <td className="artist">{track.track.artists[0].fullName}</td>
      <td>
        <LineGraph
          interval={{
            start: dates[dates.length - 1],
            end: dates[0],
          }}
          data={[data]}
          width={600}
          height={100}
          highlightIntervals={track.weeks.map(
            ({ interval, changePercentage, average }) => ({
              interval: {
                start: new Date(interval.start),
                end: new Date(interval.end),
              },
              changePercentage,
              heightValue: average ?? 0,
            })
          )}
          maxChangePercentage={maxChangePercentage}
          stroke={colors.platform.apple}
        />
      </td>
    </tr>
  );
};

export const Table: React.FC<{
  id: string;
  tracks: LabelAnalysisTrackFieldsFragment[] | null;
  caption: string;
  subCaption: string;
  maxChangePercentage: number;
  trackAnalysisMetric: TrackAnalysisMetric;
}> = ({
  id,
  tracks,
  caption,
  subCaption,
  trackAnalysisMetric,
  maxChangePercentage,
}) => {
  return (
    <div id={id} className="category">
      <h2>{caption}</h2>
      <h3>{subCaption}</h3>

      <table>
        <colgroup>
          <col />
          <col />
          <col />
          <col className="streams-graph" />
        </colgroup>
        <thead>
          <tr>
            <th colSpan={2}>Track</th>
            <th>Artist</th>
            <th className="streams-graph">
              <span className="highlight">
                {metricNames[trackAnalysisMetric]}
              </span>{" "}
              with week over week change
            </th>
          </tr>
        </thead>
        <tbody>
          {tracks != null &&
            tracks.length > 0 &&
            tracks
              /*               .sort(
                (a, b) =>
                  (b.fullIntervalByDay.find(
                    ({ date }) => date === dataCompletenessDate
                  )?.data ?? 0) -
                  (a.fullIntervalByDay.find(
                    ({ date }) => date === dataCompletenessDate
                  )?.data ?? 0)
              ) */
              .map((track) => (
                <TrackRow
                  key={track.track.isrc}
                  track={track}
                  maxChangePercentage={maxChangePercentage}
                />
              ))}
        </tbody>
      </table>
    </div>
  );
};

export const LabelFilter: React.FC<{
  labels: LabelFieldsFragment[];
  labelId: string;
  setLabelId: (labelId: string) => void;
}> = ({ labels, labelId, setLabelId }) => {
  return (
    <label className="filter">
      label:
      <select
        value={labelId}
        onChange={(e) => {
          setLabelId(e.currentTarget.value);
        }}
      >
        {labels.map(({ id, name }) => (
          <option key={id} value={id}>
            {name}
          </option>
        ))}
      </select>
    </label>
  );
};

export const MarketFilter: React.FC<{
  markets: MarketFieldsFragment[];
  market: string;
  setMarket: (market: string) => void;
}> = ({ markets, market, setMarket }) => {
  return (
    <label className="filter">
      market:
      <select
        value={market}
        onChange={(e) => {
          setMarket(e.currentTarget.value);
        }}
      >
        {markets.map(({ id, countryName }) => (
          <option key={id} value={id}>
            {countryName}
          </option>
        ))}
      </select>
    </label>
  );
};

export const StreamsThresholdFilter: React.FC<{
  threshold: number;
  setThreshold: (threshold: number) => void;
}> = ({ threshold, setThreshold }) => {
  return (
    <label className="filter">
      threshold:
      <select
        value={threshold}
        onChange={(e) => {
          setThreshold(Number.parseInt(e.currentTarget.value, 10));
        }}
      >
        {streamThresholds.map((threshold) => (
          <option key={threshold.toString()} value={threshold.toString()}>
            {formatCountShort(threshold)}
          </option>
        ))}
      </select>
    </label>
  );
};

export const StreamsFilter: React.FC<{
  analysisMetric: TrackAnalysisMetric;
  setAnalysisMetric: (metric: TrackAnalysisMetric) => void;
}> = ({ analysisMetric, setAnalysisMetric }) => {
  return (
    <label className="filter">
      filtered by:
      <select
        value={analysisMetric}
        onChange={(e) => {
          setAnalysisMetric(e.currentTarget.value as TrackAnalysisMetric);
        }}
      >
        {Object.entries(metricNames).map(([metric, name]) => (
          <option key={metric} value={metric}>
            {name}
          </option>
        ))}
      </select>
    </label>
  );
};

export const LabelTracks: React.FC<{}> = () => {
  useEffect(() => {
    amplitude.getInstance().logEvent("Label Tracks Page loaded");
  }, []);

  const [labelsResult] = useLabelsQuery({
    variables: {},
  });
  const labels = labelsResult.data?.labels.edges.map(({ node }) => node);
  const [labelId, setLabelId] = useState<string>("rca");

  const [regionsResult] = useRegionsQuery({
    variables: {},
  });
  const markets = regionsResult.data?.regions;
  const [market, setMarket] = useState<string>("worldwide");

  const [analysisMetric, setAnalysisMetric] = useState<TrackAnalysisMetric>(
    TrackAnalysisMetric.StreamsTotal
  );

  const [streamsThreshold, setStreamsThreshold] = useState<number>(1000);

  const [result] = useLabelTrackAnalysisQuery({
    variables: {
      labelId,
      trackAnalysisOptions: {
        trackReleaseInterval: {
          //TODO: Add support for omitting start or end date
          start: df.formatISO(new Date(0), {
            representation: "date",
          }),
          end: df.formatISO(df.subWeeks(df.endOfToday(), 3), {
            representation: "date",
          }),
        },
        analysisMetric,
        market,
        dspId: null,
      },
    },
  });

  const { data, error } = result;

  const tracks = data?.label?.trackAnalysis.filter((track) => {
    const streams = track.metrics
      .sort(sortByDate)
      .find(({ streams }) => streams != null)?.streams;

    return streams != null && streams > streamsThreshold;
  });

  const breakingOut =
    tracks?.filter((track) =>
      track.categories.includes(TrackAnalysisCategory.BreakingOut)
    ) ?? null;
  const gainingMomentum =
    tracks?.filter(
      (track) =>
        !track.categories.includes(TrackAnalysisCategory.BreakingOut) &&
        track.categories.includes(TrackAnalysisCategory.GainingMomentum)
    ) ?? null;
  const microMoment =
    tracks?.filter(
      (track) =>
        !track.categories.includes(TrackAnalysisCategory.BreakingOut) &&
        !track.categories.includes(TrackAnalysisCategory.GainingMomentum) &&
        track.categories.includes(TrackAnalysisCategory.MicroMoment)
    ) ?? null;

  if (error) {
    return <div>Oops... {error.message}</div>;
  }

  const maxChangePercentage = Math.max(
    ...(tracks?.flatMap(
      (track) =>
        track.weeks.flatMap((week) => week.changePercentage ?? []) ?? []
    ) ?? [])
  );

  return (
    <main>
      <div>
        {data === null && (
          <div className="loading-message">
            We admit, this first load is a slow one, but we promise the next
            loads are quick. Thank you for your patience. 😀
          </div>
        )}
        <LabelFilter
          labels={labels ?? []}
          labelId={labelId}
          setLabelId={setLabelId}
        />
        <MarketFilter
          markets={markets ?? []}
          market={market}
          setMarket={setMarket}
        />
        <StreamsFilter
          analysisMetric={analysisMetric}
          setAnalysisMetric={setAnalysisMetric}
        />
        <StreamsThresholdFilter
          threshold={streamsThreshold}
          setThreshold={setStreamsThreshold}
        />
        {result.fetching ? (
          <div className="loading-message">
            Thanks for your patience, the first couple of loads take a bit of
            time as we are still in a prototype
            <ActivityIndicator />
          </div>
        ) : (
          <>
            <Table
              id="3-weeks"
              tracks={breakingOut}
              caption={"Breaking out 🚀"}
              subCaption={"3 consecutive weeks of >10% stream growth"}
              maxChangePercentage={maxChangePercentage}
              trackAnalysisMetric={analysisMetric}
            />
            <Table
              id="2-weeks"
              tracks={gainingMomentum}
              caption={"Gaining momentum 🔥"}
              subCaption={"2 consecutive weeks of >10% stream growth"}
              maxChangePercentage={maxChangePercentage}
              trackAnalysisMetric={analysisMetric}
            />
            <Table
              id="1-week"
              tracks={microMoment}
              caption={"Micro-moment 👀"}
              subCaption={"1 week of >10% stream growth"}
              maxChangePercentage={maxChangePercentage}
              trackAnalysisMetric={analysisMetric}
            />
          </>
        )}
      </div>
    </main>
  );
};
