import { callable, isNullish } from 'mixlea-utils-js';

import type { Pipeline, PipelineState } from '../pipeline';
import { MlButtonList, type MlButtonListProps } from '@/components/ml-button-list';

export interface HeaderLeftButtonListExtensionConfig {
  defaultState?: any;
  getProps: (opts: {
    formData: PipelineState['formData'];
    headerLeftSlotState: PipelineState['headerLeftSlot'];
    headerRightSlotState: PipelineState['headerRightSlot'];
    footerLeftSlotState: PipelineState['footerLeftSlot'];
    footerRightSlotState: PipelineState['footerRightSlot'];
    headerLeftButtonListState: PipelineState['headerLeftButtonList'];
    headerRightButtonListState: PipelineState['headerRightButtonList'];
    footerLeftButtonListState: PipelineState['footerLeftButtonList'];
    footerRightButtonListState: PipelineState['footerRightButtonList'];

    setStateAtKey: Pipeline['setStateAtKey'];
    setPartialState: Pipeline['setPartialState'];
  }) => MlButtonListProps;
  onChange?: (nextState: any) => void;
}

export function headerLeftButtonListExtension(config?: HeaderLeftButtonListExtensionConfig) {
  if (isNullish(config)) {
    return (pipeline: Pipeline) => pipeline;
  }

  return function (pipeline: Pipeline) {
    const getProps = config.getProps;
    const onChange = config.onChange;

    const pipelineState = pipeline.getState();

    const setStateAtKey: Pipeline['setStateAtKey'] = (key, partialState) =>
      pipeline.setStateAtKey(key, partialState).then((pipelineState) => {
        if (key === 'headerLeftButtonList') {
          onChange?.(pipelineState.headerLeftButtonList);
        }

        return pipelineState;
      });
    const setPartialState: Pipeline['setPartialState'] = (partialState) => {
      let isChange = false;

      return pipeline
        .setPartialState((prevState) => {
          const nextPartialState = callable(partialState, prevState);

          if ('headerLeftButtonList' in nextPartialState) {
            isChange = true;
          }

          return nextPartialState;
        })
        .then((pipelineState) => {
          if (isChange) {
            onChange?.(pipelineState.headerLeftButtonList);
          }

          return pipelineState;
        });
    };

    pipeline.appendHeaderLeftSlots(() => {
      const buttonListProps = getProps({
        formData: pipelineState.formData,
        headerLeftSlotState: pipelineState.headerLeftSlot,
        headerRightSlotState: pipelineState.headerRightSlot,
        footerLeftSlotState: pipelineState.footerLeftSlot,
        footerRightSlotState: pipelineState.footerRightSlot,
        headerLeftButtonListState: pipelineState.headerLeftButtonList,
        headerRightButtonListState: pipelineState.headerRightButtonList,
        footerLeftButtonListState: pipelineState.footerLeftButtonList,
        footerRightButtonListState: pipelineState.footerRightButtonList,

        setStateAtKey,
        setPartialState,
      });

      return <MlButtonList height="full" theme="flat" {...buttonListProps} />;
    });

    return pipeline;
  };
}
