import { createSelector } from '@reduxjs/toolkit';

import type { NodeDescription } from '../../types';
import type { HostsTreeState } from './index';

export const NO_CATEGORY_LABEL = 'hosts without category';
export const ROOT_LABEL = 'All hosts';

interface RootStateSlice {
  hostsTree: HostsTreeState;
}

const selectTree = (state: RootStateSlice) => state.hostsTree;

export const selectProfiles = createSelector([selectTree], t => t.profiles);
export const selectProfilesStatus = createSelector([selectTree], t => t.profilesStatus);
export const selectProfilesError = createSelector([selectTree], t => t.profilesError);
export const selectSelectedProfileId = createSelector([selectTree], t => t.selectedProfileId);

export const selectSelectedProfile = createSelector(
  [selectProfiles, selectSelectedProfileId],
  (profiles, id) => (id === null ? null : profiles.find(p => String(p.id) === String(id)) ?? null)
);

export const selectTreeStatus = createSelector([selectTree], t => t.treeStatus);
export const selectTreeError = createSelector([selectTree], t => t.treeError);
export const selectTreeRefreshKey = createSelector([selectTree], t => t.treeRefreshKey);
export const selectNodeChildren = createSelector([selectTree], t => t.nodeChildren);

// Synthetic root used by the legacy widget. "All hosts" wraps the server's
// children and appends a `hosts without category` super-node so excludes are
// derived from siblings.
export const selectNodeTree = createSelector([selectNodeChildren], (children): NodeDescription | null => {
  if (children === null) return null;
  const wrapped: NodeDescription[] = [...children];
  if (children.length > 0) {
    const excludes = children
      .map(n => n.classRegex)
      .filter(Boolean)
      .join('|');
    wrapped.push({
      label: NO_CATEGORY_LABEL,
      classRegex: '.*',
      children: [],
      isRemovable: false,
      superNode: true,
      excludes
    });
  }
  return {
    label: ROOT_LABEL,
    classRegex: '.*',
    children: wrapped,
    isRemovable: true,
    superNode: true
  };
});

export const selectCountMap = createSelector([selectTree], t => t.countMap);
export const selectCountsLoading = createSelector([selectTree], t => t.countsLoading);

export const selectTreeMetadata = createSelector([selectTree], t => t.treeMetadata);
export const selectTreeMetadataLoaded = createSelector([selectTree], t => t.treeMetadataLoaded);

export const selectClasses = createSelector([selectTree], t => t.classes);

export const selectSubscribable = createSelector([selectTree], t => t.subscribable);

export const selectProfileSettings = (id: number | string | null) =>
  createSelector([selectTree], t => (id == null ? null : t.profileSettings[String(id)] ?? null));

export const selectNodeHosts = (key: string) =>
  createSelector([selectTree], t => t.nodeHosts[key]);

export const selectTreeLoadingStates = createSelector([selectTree], t => t.loadingStates);

export const selectIsTreeBusy = createSelector(
  [selectProfilesStatus, selectTreeStatus, selectCountsLoading],
  (profilesStatus, treeStatus, countsLoading) =>
    profilesStatus === 'loading' || treeStatus === 'loading' || countsLoading
);
