import { findAllAdHocFiltersInHierarchy, findGlobalAdHocFilterVariableByUid } from './adhoc/patchGetAdhocFilters.js';
import { findClosestGroupByInHierarchy, findGlobalGroupByVariableByUid } from './groupby/findActiveGroupByVariablesByUid.js';
import { isFilterComplete, isFilterApplicable, isGroupByFilter } from './adhoc/AdHocFiltersVariable.js';
import { getAdHocFiltersFromScopes } from './adhoc/getAdHocFiltersFromScopes.js';
import { getScopes } from '../core/sceneGraph/sceneGraph.js';
import { SCOPES_VARIABLE_NAME } from './constants.js';

class DrilldownDependenciesManager {
  constructor(variableDependency) {
    /** All matching AdHocFiltersVariables from root → leaf for query-time merge */
    this._adhocFiltersVars = [];
    this._variableDependency = variableDependency;
  }
  /**
   * Find drilldown variables matching the given datasource UID.
   * When sceneObject is provided, walks up the hierarchy and collects all matches
   * so parent filters/scopes can be merged at query time.
   * Otherwise falls back to searching the global active variable sets.
   */
  findAndSubscribeToDrilldowns(interpolatedUid, sceneObject) {
    this._sceneObject = sceneObject;
    const filtersVars = sceneObject ? findAllAdHocFiltersInHierarchy(interpolatedUid, sceneObject) : (() => {
      const globalVar = findGlobalAdHocFilterVariableByUid(interpolatedUid);
      return globalVar ? [globalVar] : [];
    })();
    const filtersVar = filtersVars.length > 0 ? filtersVars[filtersVars.length - 1] : void 0;
    const useAdhocGroupBy = (filtersVar == null ? void 0 : filtersVar.state.enableGroupBy) === true;
    const groupByVar = useAdhocGroupBy ? void 0 : sceneObject ? findClosestGroupByInHierarchy(interpolatedUid, sceneObject) : findGlobalGroupByVariableByUid(interpolatedUid);
    let hasChanges = false;
    if (!areSameAdHocVars(this._adhocFiltersVars, filtersVars)) {
      this._adhocFiltersVars = filtersVars;
      this._adhocFiltersVar = filtersVar;
      hasChanges = true;
    }
    if (this._groupByVar !== groupByVar) {
      this._groupByVar = groupByVar;
      hasChanges = true;
    }
    if (hasChanges) {
      this._updateExplicitDrilldownVariableDependencies();
    }
  }
  _updateExplicitDrilldownVariableDependencies() {
    const explicitDependencies = [];
    for (const filtersVar of this._adhocFiltersVars) {
      explicitDependencies.push(filtersVar.state.name);
    }
    if (this._adhocFiltersVars.length > 0) {
      explicitDependencies.push(SCOPES_VARIABLE_NAME);
    }
    if (this._groupByVar) {
      explicitDependencies.push(this._groupByVar.state.name);
    }
    this._variableDependency.setVariableNames(explicitDependencies);
  }
  get adHocFiltersVar() {
    return this._adhocFiltersVar;
  }
  get adHocFiltersVars() {
    return this._adhocFiltersVars;
  }
  get groupByVar() {
    return this._groupByVar;
  }
  isSubscribedAdHocFiltersVar(variable) {
    return this._adhocFiltersVars.includes(variable);
  }
  _getMergedFilters() {
    var _a;
    if (this._adhocFiltersVars.length === 0) {
      return [];
    }
    const fromVars = [];
    const seen = /* @__PURE__ */ new Set();
    const scopeKeysFromVars = /* @__PURE__ */ new Set();
    for (const filtersVar of this._adhocFiltersVars) {
      for (const filter of [...(_a = filtersVar.state.originFilters) != null ? _a : [], ...filtersVar.state.filters]) {
        const key = filterIdentityKey(filter);
        if (seen.has(key)) {
          continue;
        }
        seen.add(key);
        if (filter.origin === "scope") {
          scopeKeysFromVars.add(filter.key);
        }
        fromVars.push(filter);
      }
    }
    const fromScopes = [];
    if (this._sceneObject) {
      const scopes = getScopes(this._sceneObject);
      if (scopes == null ? void 0 : scopes.length) {
        for (const filter of getAdHocFiltersFromScopes(scopes)) {
          if (scopeKeysFromVars.has(filter.key)) {
            continue;
          }
          const key = filterIdentityKey(filter);
          if (seen.has(key)) {
            continue;
          }
          seen.add(key);
          fromScopes.push(filter);
        }
      }
    }
    return [...fromScopes, ...fromVars];
  }
  /**
   * Returns only "real" ad-hoc filters, excluding groupBy entries embedded in the filters array.
   * Merges scope + ancestor + section filters when multiple AdHoc vars exist in the hierarchy.
   */
  getFilters() {
    if (this._adhocFiltersVars.length === 0) {
      return void 0;
    }
    return this._getMergedFilters().filter((f) => isFilterComplete(f) && isFilterApplicable(f) && !isGroupByFilter(f));
  }
  /**
   * Returns group-by keys. When the closest adhoc variable has enableGroupBy=true, extracts
   * them from that variable's filters array (operator === 'groupBy'). Otherwise falls back to
   * the legacy GroupByVariable.
   */
  getGroupByKeys() {
    var _a, _b;
    if ((_a = this._adhocFiltersVar) == null ? void 0 : _a.state.enableGroupBy) {
      const groupByKeys = [...(_b = this._adhocFiltersVar.state.originFilters) != null ? _b : [], ...this._adhocFiltersVar.state.filters].filter((f) => isGroupByFilter(f) && isFilterComplete(f) && isFilterApplicable(f)).map((f) => f.key);
      return groupByKeys.length > 0 ? groupByKeys : void 0;
    }
    return this._groupByVar ? this._groupByVar.getApplicableKeys() : void 0;
  }
  cleanup() {
    this._adhocFiltersVar = void 0;
    this._adhocFiltersVars = [];
    this._groupByVar = void 0;
    this._sceneObject = void 0;
  }
}
function areSameAdHocVars(a, b) {
  if (a.length !== b.length) {
    return false;
  }
  return a.every((v, i) => v === b[i]);
}
function filterIdentityKey(filter) {
  var _a, _b, _c;
  const values = (_b = (_a = filter.values) == null ? void 0 : _a.join(",")) != null ? _b : filter.value;
  return `${(_c = filter.origin) != null ? _c : ""}|${filter.key}|${filter.operator}|${values}`;
}

export { DrilldownDependenciesManager };
//# sourceMappingURL=DrilldownDependenciesManager.js.map
