import React from 'react';
import { store } from '@grafana/data';
import { sceneGraph } from '../../core/sceneGraph/index.js';
import { getEnrichedDataRequest } from '../../querying/getEnrichedDataRequest.js';
import { getQueriesForVariables } from '../utils.js';
import { getDataSource } from '../../utils/getDataSource.js';
import { DrilldownRecommendations } from '../components/DrilldownRecommendations.js';
import { ScopesVariable } from '../variants/ScopesVariable.js';
import { SCOPES_VARIABLE_NAME } from '../constants.js';
import { GroupByVariable } from './GroupByVariable.js';
import '../adhoc/AdHocFiltersRecommendations.js';
import { isArray } from 'lodash';
import { SceneObjectBase } from '../../core/SceneObjectBase.js';
import { wrapInSafeSerializableSceneObject } from '../../utils/wrapInSafeSerializableSceneObject.js';

const getRecentGroupingKey = (datasourceUid) => `grafana.grouping.recent.${datasourceUid != null ? datasourceUid : "default"}`;
class GroupByRecommendations extends SceneObjectBase {
  constructor(state = {}) {
    super(state);
    this._activationHandler = () => {
      const json = store.get(this._getStorageKey());
      const storedGroupings = json ? JSON.parse(json) : [];
      if (storedGroupings.length > 0) {
        this._verifyRecentGroupingsApplicability(storedGroupings);
      } else {
        this.setState({ recentGrouping: [] });
      }
      this._fetchRecommendedDrilldowns();
      const scopesVariable = sceneGraph.lookupVariable(SCOPES_VARIABLE_NAME, this._groupBy);
      let scopesSubscription;
      let groupBySubscription;
      if (scopesVariable instanceof ScopesVariable) {
        this._subs.add(
          scopesSubscription = scopesVariable.subscribeToState((newState, prevState) => {
            if (newState.scopes !== prevState.scopes) {
              const json2 = store.get(this._getStorageKey());
              const storedGroupings2 = json2 ? JSON.parse(json2) : [];
              if (storedGroupings2.length > 0) {
                this._verifyRecentGroupingsApplicability(storedGroupings2);
              }
              this._fetchRecommendedDrilldowns();
            }
          })
        );
      }
      this._subs.add(
        groupBySubscription = this._groupBy.subscribeToState((newState, prevState) => {
          if (newState.value !== prevState.value) {
            const json2 = store.get(this._getStorageKey());
            const storedGroupings2 = json2 ? JSON.parse(json2) : [];
            if (storedGroupings2.length > 0) {
              this._verifyRecentGroupingsApplicability(storedGroupings2);
            }
            this._fetchRecommendedDrilldowns();
          }
        })
      );
      return () => {
        scopesSubscription == null ? void 0 : scopesSubscription.unsubscribe();
        groupBySubscription == null ? void 0 : groupBySubscription.unsubscribe();
      };
    };
    this.addActivationHandler(this._activationHandler);
  }
  get _groupBy() {
    if (!(this.parent instanceof GroupByVariable)) {
      throw new Error("GroupByRecommendations must be a child of GroupByVariable");
    }
    return this.parent;
  }
  get _scopedVars() {
    return { __sceneObject: wrapInSafeSerializableSceneObject(this._groupBy) };
  }
  _getStorageKey() {
    var _a;
    return getRecentGroupingKey((_a = this._groupBy.state.datasource) == null ? void 0 : _a.uid);
  }
  async _fetchRecommendedDrilldowns() {
    const ds = await getDataSource(this._groupBy.state.datasource, this._scopedVars);
    if (!ds || !ds.getRecommendedDrilldowns) {
      return;
    }
    const queries = getQueriesForVariables(this._groupBy);
    const timeRange = sceneGraph.getTimeRange(this._groupBy).state.value;
    const scopes = sceneGraph.getScopes(this._groupBy);
    const groupByKeys = Array.isArray(this._groupBy.state.value) ? this._groupBy.state.value.map((v) => String(v)) : this._groupBy.state.value ? [String(this._groupBy.state.value)] : [];
    const enrichedRequest = getEnrichedDataRequest(this._groupBy);
    const dashboardUid = enrichedRequest == null ? void 0 : enrichedRequest.dashboardUID;
    try {
      const recommendedDrilldowns = await ds.getRecommendedDrilldowns({
        timeRange,
        dashboardUid,
        queries,
        groupByKeys,
        scopes
      });
      if (recommendedDrilldowns == null ? void 0 : recommendedDrilldowns.groupByKeys) {
        this.setState({
          recommendedGrouping: recommendedDrilldowns.groupByKeys.map((key) => ({ value: key, text: key }))
        });
      }
    } catch (error) {
      console.error("Failed to fetch recommended drilldowns:", error);
    }
  }
  async _verifyRecentGroupingsApplicability(storedGroupings) {
    const queries = getQueriesForVariables(this._groupBy);
    const keys = storedGroupings.map((g) => String(g.value));
    const response = await this._groupBy.getGroupByApplicabilityForQueries(keys, queries);
    if (!response) {
      this.setState({ recentGrouping: storedGroupings.slice(-3) });
      return;
    }
    const applicabilityMap = /* @__PURE__ */ new Map();
    response.forEach((item) => {
      applicabilityMap.set(item.key, item.applicable !== false);
    });
    const applicableGroupings = storedGroupings.filter((g) => {
      const isApplicable = applicabilityMap.get(String(g.value));
      return isApplicable === void 0 || isApplicable === true;
    }).slice(-3);
    this.setState({ recentGrouping: applicableGroupings });
  }
  /**
   * Stores recent groupings in localStorage and updates state.
   * Should be called by the parent variable when a grouping is added/updated.
   */
  storeRecentGrouping(applicableValues) {
    if (applicableValues.length === 0) {
      return;
    }
    const key = this._getStorageKey();
    const storedGroupings = store.get(key);
    const allRecentGroupings = storedGroupings ? JSON.parse(storedGroupings) : [];
    const existingWithoutApplicableValues = allRecentGroupings.filter(
      (grouping) => !applicableValues.includes(String(grouping.value))
    );
    const updatedStoredGroupings = [
      ...existingWithoutApplicableValues,
      ...applicableValues.map((value) => ({ value, text: value }))
    ];
    const limitedStoredGroupings = updatedStoredGroupings.slice(-10);
    store.set(key, JSON.stringify(limitedStoredGroupings));
    this.setState({ recentGrouping: limitedStoredGroupings.slice(-3) });
  }
  /**
   * Add a grouping value to the parent variable
   */
  addValueToParent(newValue, newText) {
    const value = isArray(this._groupBy.state.value) ? this._groupBy.state.value : [this._groupBy.state.value];
    const text = isArray(this._groupBy.state.text) ? this._groupBy.state.text.map(String) : [String(this._groupBy.state.text)];
    if (value.includes(newValue)) {
      return;
    }
    this._groupBy.changeValueTo(
      [...value.filter((v) => v !== ""), newValue],
      [...text.filter((t) => t !== ""), newText != null ? newText : String(newValue)],
      true
    );
  }
}
GroupByRecommendations.Component = GroupByRecommendationsRenderer;
function GroupByRecommendationsRenderer({ model }) {
  const { recentGrouping, recommendedGrouping } = model.useState();
  const recentDrilldowns = recentGrouping == null ? void 0 : recentGrouping.map((groupBy) => ({
    label: `${groupBy.value}`,
    onClick: () => {
      var _a;
      model.addValueToParent(groupBy.value, (_a = groupBy.text) != null ? _a : String(groupBy.value));
    }
  }));
  const recommendedDrilldowns = recommendedGrouping == null ? void 0 : recommendedGrouping.map((groupBy) => ({
    label: `${groupBy.value}`,
    onClick: () => {
      var _a;
      model.addValueToParent(groupBy.value, (_a = groupBy.text) != null ? _a : String(groupBy.value));
    }
  }));
  return /* @__PURE__ */ React.createElement(DrilldownRecommendations, { recentDrilldowns, recommendedDrilldowns });
}

export { GroupByRecommendations, getRecentGroupingKey };
//# sourceMappingURL=GroupByRecommendations.js.map
