import { Children } from 'react';
import { useToolbarCollectionContext } from '../ToolbarCollectionContext';
import { FilterElement } from './filterElement';
import type { renderPresetToolbarTag } from '../DateRangeFilter/renderPresetToolbarTag';

type FilterChild = FilterElement | undefined | boolean;
type FilterChildren = FilterChild | FilterChild[];
type FilterChildComponent = FilterElement & {
  type: {
    displayName?: string;
    renderPresetToolbarTag?: typeof renderPresetToolbarTag;
  };
};
type FilterChildrenComponent = FilterChildComponent[];

function hasFilter(e: FilterChildComponent, index: number) {
  const filter = e?.props?.filter;
  if (process.env.NODE_ENV !== 'production') {
    if (filter == null) {
      console.warn(
        `filter component must pass \`filter\` prop directly, missing from CollectionToolbarFilters.children[${index}].props`,
      );
    }
  }
  return filter != null;
}

function flattenChildren(children: FilterChildren) {
  const currentChildren = [];

  if (Array.isArray(children)) {
    currentChildren.push(...children);
  } else {
    currentChildren.push(children);
  }

  return currentChildren;
}

function filterValidChildren(children: FilterChildren) {
  return (Children.toArray(children) as FilterChildrenComponent).filter(
    hasFilter,
  );
}

function addTagsFilter(
  children: FilterChildrenComponent,
  state: ReturnType<typeof useToolbarCollectionContext>,
) {
  const tagsFilter = state.tagsCollectionState?.buildTagsFilterWrapper();
  if (
    tagsFilter &&
    !children.some(
      (child) => child.props.filter.name === tagsFilter.props.filter.name,
    )
  ) {
    return [...children, tagsFilter as FilterChildComponent];
  }

  return children;
}

function addCustomFieldFilters(
  children: FilterChildrenComponent,
  state: ReturnType<typeof useToolbarCollectionContext>,
) {
  const customFieldFilters =
    state.collectionDataExtension?.dataExtension.filterableCustomFields
      .map((customField) => {
        if (
          children.some((child) => child.props.filter.name === customField.id)
        ) {
          return null;
        }

        return state.collectionDataExtension?.buildCustomFieldFilterWrapper(
          customField,
        );
      })
      .filter(Boolean) as FilterChildComponent[] | undefined;
  if (customFieldFilters) {
    return [...children, ...customFieldFilters];
  }

  return children;
}

export const useFiltersSyncProps = (children: FilterChildren) => {
  const state = useToolbarCollectionContext();
  const allChildren = flattenChildren(children);
  const filteredChildren = filterValidChildren(allChildren);
  const childrenWithTagsFilter = addTagsFilter(filteredChildren, state);
  const finalChildren = addCustomFieldFilters(childrenWithTagsFilter, state);
  return finalChildren;
};
