import { css } from '@emotion/css';
import pluralize from 'pluralize';
import React, { useMemo } from 'react';
import { useLocation } from 'react-router-dom';

import { GrafanaTheme2, urlUtil } from '@grafana/data';
import { LinkButton, LoadingPlaceholder, Pagination, Spinner, useStyles2 } from '@grafana/ui';
import { CombinedRuleNamespace } from 'app/types/unified-alerting';

import { DEFAULT_PER_PAGE_PAGINATION } from '../../../../../core/constants';
import { AlertingAction, useAlertingAbility } from '../../hooks/useAbilities';
import { usePagination } from '../../hooks/usePagination';
import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector';
import { getPaginationStyles } from '../../styles/pagination';
import { getRulesDataSources, getRulesSourceUid } from '../../utils/datasource';
import { isAsyncRequestStatePending } from '../../utils/redux';

import { RulesGroup } from './RulesGroup';
import { useCombinedGroupNamespace } from './useCombinedGroupNamespace';

interface Props {
  namespaces: CombinedRuleNamespace[];
  expandAll: boolean;
}

export const CloudRules = ({ namespaces, expandAll }: Props) => {
  const styles = useStyles2(getStyles);

  const dsConfigs = useUnifiedAlertingSelector((state) => state.dataSources);
  const promRules = useUnifiedAlertingSelector((state) => state.promRules);
  const rulesDataSources = useMemo(getRulesDataSources, []);
  const groupsWithNamespaces = useCombinedGroupNamespace(namespaces);

  const dataSourcesLoading = useMemo(
    () =>
      rulesDataSources.filter(
        (ds) => isAsyncRequestStatePending(promRules[ds.name]) || isAsyncRequestStatePending(dsConfigs[ds.name])
      ),
    [promRules, dsConfigs, rulesDataSources]
  );

  const hasSomeResults = rulesDataSources.some((ds) => Boolean(promRules[ds.name]?.result?.length));

  const hasDataSourcesConfigured = rulesDataSources.length > 0;
  const hasDataSourcesLoading = dataSourcesLoading.length > 0;
  const hasNamespaces = namespaces.length > 0;

  const { numberOfPages, onPageChange, page, pageItems } = usePagination(
    groupsWithNamespaces,
    1,
    DEFAULT_PER_PAGE_PAGINATION
  );

  return (
    <section className={styles.wrapper}>
      <div className={styles.sectionHeader}>
        <div className={styles.headerRow}>
          <h5>Mimir / Cortex / Loki</h5>
          {dataSourcesLoading.length ? (
            <LoadingPlaceholder
              className={styles.loader}
              text={`Loading rules from ${dataSourcesLoading.length} ${pluralize('source', dataSourcesLoading.length)}`}
            />
          ) : (
            <div />
          )}
          <CreateRecordingRuleButton />
        </div>
      </div>

      {pageItems.map(({ group, namespace }) => {
        return (
          <RulesGroup
            group={group}
            key={`${getRulesSourceUid(namespace.rulesSource)}-${namespace.name}-${group.name}`}
            namespace={namespace}
            expandAll={expandAll}
            viewMode={'grouped'}
          />
        );
      })}

      {!hasDataSourcesConfigured && <p>There are no Prometheus or Loki data sources configured.</p>}
      {hasDataSourcesConfigured && !hasDataSourcesLoading && !hasNamespaces && <p>No rules found.</p>}
      {!hasSomeResults && hasDataSourcesLoading && <Spinner size="xl" className={styles.spinner} />}

      <Pagination
        className={styles.pagination}
        currentPage={page}
        numberOfPages={numberOfPages}
        onNavigate={onPageChange}
        hideWhenSinglePage
      />
    </section>
  );
};

const getStyles = (theme: GrafanaTheme2) => ({
  loader: css`
    margin-bottom: 0;
  `,
  sectionHeader: css`
    display: flex;
    justify-content: space-between;
  `,
  wrapper: css`
    margin-bottom: ${theme.spacing(4)};
  `,
  spinner: css`
    text-align: center;
    padding: ${theme.spacing(2)};
  `,
  pagination: getPaginationStyles(theme),
  headerRow: css({
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'space-between',
    width: '100%',
    marginBottom: theme.spacing(1),
  }),
});

export function CreateRecordingRuleButton() {
  const [createCloudRuleSupported, createCloudRuleAllowed] = useAlertingAbility(AlertingAction.CreateExternalAlertRule);

  const location = useLocation();

  const canCreateCloudRules = createCloudRuleSupported && createCloudRuleAllowed;

  if (canCreateCloudRules) {
    return (
      <LinkButton
        key="new-recording-rule"
        href={urlUtil.renderUrl(`alerting/new/recording`, {
          returnTo: location.pathname + location.search,
        })}
        icon="plus"
        variant="secondary"
      >
        New recording rule
      </LinkButton>
    );
  }
  return null;
}
