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

import type { Pipeline, PipelineState } from '../pipeline';
import type { JSXElement } from '@/components/types';

export interface HeaderLeftSlotExtensionConfig {
  defaultState?: any;
  render: (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'];
  }) => JSXElement;
  onChange?: (nextState: any) => void;
}

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

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

    const pipelineState = pipeline.getState();

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

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

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

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

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

          return pipelineState;
        });
    };

    pipeline.appendHeaderLeftSlots(
      functionWrap(render, {
        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 pipeline;
  };
}
