import {
  all,
  equals,
  flatten,
  gt,
  isEmpty,
  length,
  map,
  pipe,
  pluck,
  project,
  uniq,
  uniqBy
} from 'ramda';

import {
  ListingModel,
  buildListingEndpoint,
  resourceTypeQueryParameter,
  useFetchQuery
} from '@centreon/ui';

import {
  Metric,
  ServiceMetric,
  WidgetDataResource,
  WidgetResourceType
} from '../../../models';

import { serviceMetricsDecoder } from '../../../api/decoders';
import { metricsEndpoint } from '../../../api/endpoints';

interface Props {
  resources: Array<WidgetDataResource>;
  selectedMetrics?: Array<Metric>;
}

interface UseListMetricsState {
  hasMultipleUnitsSelected: boolean;
  hasTooManyMetrics: boolean;
  isLoadingMetrics: boolean;
  metricCount?: number;
  metrics: Array<Metric>;
  servicesMetrics?: ListingModel<ServiceMetric>;
}

export const useListMetrics = ({
  resources,
  selectedMetrics = []
}: Props): UseListMetricsState => {
  const { data: servicesMetrics, isFetching: isLoadingMetrics } = useFetchQuery<
    ListingModel<ServiceMetric>
  >({
    decoder: serviceMetricsDecoder,
    getEndpoint: () =>
      buildListingEndpoint({
        baseEndpoint: metricsEndpoint,
        parameters: {
          limit: 1000,
          search: {
            lists: resources.map((resource) => ({
              field: equals(resource.resourceType, 'hostgroup')
                ? resourceTypeQueryParameter[WidgetResourceType.hostGroup]
                : resourceTypeQueryParameter[resource.resourceType],
              values: equals(resource.resourceType, 'service')
                ? pluck('name', resource.resources)
                : pluck('id', resource.resources)
            }))
          }
        }
      }),
    getQueryKey: () => ['metrics', JSON.stringify(resources)],
    queryOptions: {
      enabled:
        !isEmpty(resources) &&
        all((resource) => !isEmpty(resource.resources), resources),
      suspense: false
    }
  });

  const hasTooManyMetrics = gt(servicesMetrics?.meta?.total || 0, 1000);

  const metricCount = servicesMetrics?.meta?.total;

  const unitsFromSelectedMetrics = pipe(
    flatten,
    pluck('unit'),
    uniq
  )(selectedMetrics || []);

  const hasMultipleUnitsSelected = gt(length(unitsFromSelectedMetrics), 1);

  const metrics: Array<Metric> = pipe(
    project(['metrics', 'id', 'name']),
    uniqBy(({ name }) => name),
    map((item) =>
      map(
        (metric) => ({
          ...metric,
          serviceId: item?.id,
          serviceName: item?.name
        }),
        item?.metrics
      )
    ),
    flatten
  )(servicesMetrics?.result || []);

  return {
    hasMultipleUnitsSelected,
    hasTooManyMetrics,
    isLoadingMetrics,
    metricCount,
    metrics,
    servicesMetrics
  };
};
