import max from 'lodash/max';

import {useDiscoverQuery} from 'sentry/utils/discover/discoverQuery';
import type EventView from 'sentry/utils/discover/eventView';
import type {QueryFieldValue} from 'sentry/utils/discover/fields';
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import type {DataRow} from 'sentry/views/starfish/components/samplesTable/transactionSamplesTable';

const LIMIT_PER_POPULATION = 2;

/**
 * This hook will fetch transaction events from 3 different types of populations and combine them in one set, then return them:
 *
 * - Slowest Events
 * - Median / Baseline Events
 * - Fastest Events
 *
 * It assumes that you are passing an eventView object with a query scoped to a specific transaction
 *
 * @param eventView An eventView containing query information, such as the transaction and other filters
 */
export default function useSlowMedianFastSamplesQuery(
  eventView: EventView,
  graphMax?: number
) {
  const location = useLocation();
  const organization = useOrganization();

  const commonColumns: QueryFieldValue[] = [
    {
      field: 'transaction.duration',
      kind: 'field',
    },
    {
      field: 'profile_id',
      kind: 'field',
    },
    {
      field: 'timestamp',
      kind: 'field',
    },
    {
      field: 'spans.browser',
      kind: 'field',
    },
    {
      field: 'spans.db',
      kind: 'field',
    },
    {
      field: 'spans.http',
      kind: 'field',
    },
    {
      field: 'spans.resource',
      kind: 'field',
    },
    {
      field: 'spans.ui',
      kind: 'field',
    },
  ];

  const eventViewAggregates = eventView
    .clone()
    .withColumns([
      {kind: 'function', function: ['avg', 'transaction.duration', undefined, undefined]},
    ]);

  const {isLoading: isLoadingAgg, data: aggregatesData} = useDiscoverQuery({
    eventView: eventViewAggregates,
    referrer: 'starfish-transaction-summary-sample-events',
    location,
    orgSlug: organization.slug,
    options: {
      refetchOnWindowFocus: false,
      enabled: graphMax !== undefined,
    },
  });
  const avg = aggregatesData
    ? aggregatesData.data[0]['avg(transaction.duration)']
    : undefined;
  const upperThird = graphMax ? max([graphMax * (2 / 3), avg]) : undefined;
  const lowerThird = graphMax ? graphMax * (1 / 3) : undefined;

  const slowestSamplesEventView = eventView
    .clone()
    .withColumns(commonColumns)
    .withSorts([
      {
        field: 'id',
        kind: 'desc',
      },
    ]);

  slowestSamplesEventView.additionalConditions = new MutableSearch(
    `transaction.duration:<${graphMax} transaction.duration:>${upperThird}`
  );

  const {isLoading: isLoadingSlowest, data: slowestSamplesData} = useDiscoverQuery({
    eventView: slowestSamplesEventView,
    referrer: 'starfish-transaction-summary-sample-events',
    location,
    orgSlug: organization.slug,

    limit: LIMIT_PER_POPULATION,
    options: {
      refetchOnWindowFocus: false,
      enabled: graphMax !== undefined && avg !== undefined,
    },
  });

  const medianSamplesEventView = eventView
    .clone()
    .withColumns(commonColumns)
    .withSorts([
      {
        field: 'transaction.duration',
        kind: 'desc',
      },
    ]);

  medianSamplesEventView.additionalConditions = new MutableSearch(
    `transaction.duration:<=${upperThird} transaction.duration:>${lowerThird}`
  );

  const {isLoading: isLoadingMedian, data: medianSamplesData} = useDiscoverQuery({
    eventView: medianSamplesEventView,
    referrer: 'starfish-transaction-summary-sample-events',
    location,
    orgSlug: organization.slug,
    limit: LIMIT_PER_POPULATION,
    options: {
      refetchOnWindowFocus: false,
      enabled: graphMax !== undefined && avg !== undefined,
    },
  });

  const fastestSamplesEventView = eventView
    .clone()
    .withColumns(commonColumns)
    .withSorts([
      {
        field: 'transaction.duration',
        kind: 'asc',
      },
    ]);

  fastestSamplesEventView.additionalConditions = new MutableSearch(
    `transaction.duration:<=${lowerThird}`
  );

  const {isLoading: isLoadingFastest, data: fastestSamplesData} = useDiscoverQuery({
    eventView: fastestSamplesEventView,
    referrer: 'starfish-transaction-summary-sample-events',
    location,
    orgSlug: organization.slug,
    limit: LIMIT_PER_POPULATION,
    options: {
      refetchOnWindowFocus: false,
      enabled: graphMax !== undefined,
    },
  });

  if (isLoadingAgg || isLoadingSlowest || isLoadingMedian || isLoadingFastest) {
    return {isLoading: true, data: []};
  }

  const combinedData = [
    ...(slowestSamplesData?.data ?? []),
    ...(medianSamplesData?.data ?? []),
    ...(fastestSamplesData?.data ?? []),
  ];

  return {
    isLoading: false,
    data: combinedData as DataRow[],
    aggregatesData: aggregatesData?.data[0] ?? [],
  };
}
