import { Errored } from 'dashboard/core/components/errored';
import {
  useEventStreamStats,
  useEventTypeSubscribers,
} from 'dashboard/core/utils/event-stream';
import { code } from 'dashboard/generated/controlplane';
import * as _ from 'lodash';
import * as React from 'react';
import {
  Button,
  ButtonType,
  Column,
  CoreText,
  FontSize,
  Grid,
  Layout,
  LoadingSpinner,
  StyledLayout,
  SVGAsset,
  TextType,
} from 'twitch-core-ui';
import twirp = code.justin.tv.eventbus.controlplane;

interface EventStreamUsageProps {
  event: twirp.IEventStream;
}
export const EventStreamUsage = ({ event }: EventStreamUsageProps) => {
  const {
    subscribers,
    loading: subscribersLoading,
    error: subscribersError,
  } = useEventTypeSubscribers(event.eventType as string);

  const {
    minEPM,
    maxEPM,
    meanEPM,
    meanSize,
    publishers,
    loading: statsLoading,
    error: statsError,
  } = useEventStreamStats(
    event.eventType as string,
    event.environment as string,
  );

  if (statsLoading || subscribersLoading) {
    return <LoadingSpinner />;
  } else if (statsError || subscribersError) {
    return (
      <Errored
        text={
          statsError ? statsError.message : (subscribersError as Error).message
        }
      />
    );
  }

  const sortedSubscribers = _.sortBy(subscribers, (s) => s.name);
  const sortedPublishers = _.sortBy(publishers, (p) => p.name);

  return (
    <Grid>
      <Column cols={6}>
        <StyledLayout padding={0.5}>
          <EventStreamStats
            maxEPM={maxEPM}
            minEPM={minEPM}
            meanEPM={meanEPM}
            meanSize={meanSize}
          />
        </StyledLayout>
      </Column>
      <Column cols={6}>
        <StyledLayout padding={0.5}>
          <EventStreamServices
            subscribers={sortedSubscribers}
            publishers={sortedPublishers}
          />
        </StyledLayout>
      </Column>
    </Grid>
  );
};

interface EventStreamStatsProps {
  maxEPM: number | null;
  minEPM: number | null;
  meanEPM: number | null;
  meanSize: number | null;
}
const EventStreamStats = ({
  maxEPM,
  minEPM,
  meanEPM,
  meanSize,
}: EventStreamStatsProps) => (
  <Layout>
    <Layout>
      <CoreText fontSize={FontSize.Size4}>Publisher Stats</CoreText>
    </Layout>
    <StyledLayout padding={{ top: 0.5, left: 2, right: 2, bottom: 0.5 }}>
      <Grid>
        <Column cols={6}>
          <CoreText fontSize={FontSize.Size5} bold>
            Max Events per Minute
          </CoreText>
        </Column>
        <Column cols={6}>
          <CoreText fontSize={FontSize.Size5}>{formatFloat(maxEPM)}</CoreText>
        </Column>
        <Column cols={6}>
          <CoreText fontSize={FontSize.Size5} bold>
            Min Events Per Minute
          </CoreText>
        </Column>
        <Column cols={6}>
          <CoreText fontSize={FontSize.Size5}>{formatFloat(minEPM)}</CoreText>
        </Column>
        <Column cols={6}>
          <CoreText fontSize={FontSize.Size5} bold>
            Average Events Per Minute
          </CoreText>
        </Column>
        <Column cols={6}>
          <CoreText fontSize={FontSize.Size5}>{formatFloat(meanEPM)}</CoreText>
        </Column>
        <Column cols={6}>
          <CoreText fontSize={FontSize.Size5} bold>
            Average Event Size
          </CoreText>
        </Column>
        <Column cols={6}>
          <CoreText fontSize={FontSize.Size5}>
            {meanEPM ? `${formatFloat(meanSize)}B` : 'N/A'}
          </CoreText>
        </Column>
      </Grid>
    </StyledLayout>
  </Layout>
);

interface EventStreamServicesProps {
  subscribers: twirp.IService[];
  publishers: twirp.IPublisherServiceInfo[];
}
const EventStreamServices = ({
  subscribers,
  publishers,
}: EventStreamServicesProps) => (
  <Layout>
    <Layout>
      <CoreText fontSize={FontSize.Size4}>Publishers</CoreText>
    </Layout>
    <StyledLayout padding={{ top: 0.5, left: 2, right: 2, bottom: 0.5 }}>
      {_.isEmpty(publishers) ? (
        <CoreText type={TextType.Em}>No publishers for this event</CoreText>
      ) : (
        _.map(publishers, (p) => (
          <Layout>
            <Button
              type={ButtonType.Text}
              linkTo={`${p.serviceCatalogUrl}`}
              icon={SVGAsset.Popout}
            >
              {p.name}
            </Button>
          </Layout>
        ))
      )}
    </StyledLayout>
    <Layout>
      <CoreText fontSize={FontSize.Size4}>Subscribers</CoreText>
    </Layout>
    <StyledLayout padding={{ top: 0.5, left: 2, right: 2, bottom: 0.5 }}>
      {_.isEmpty(subscribers) ? (
        <CoreText type={TextType.Em}>No subscribers for this event</CoreText>
      ) : (
        _.map(subscribers, (s) => (
          <Layout>
            <Button
              type={ButtonType.Text}
              linkTo={`${s.serviceCatalogUrl}`}
              icon={SVGAsset.Popout}
            >
              {s.name}
            </Button>
          </Layout>
        ))
      )}
    </StyledLayout>
  </Layout>
);

const formatFloat = (val: number | null | undefined) => {
  if (!val) {
    return 'N/A';
  }
  return `${val.toFixed(2)}`;
};
