import './index.scss';

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

import type { Pipeline } from '../pipeline';
import type { CellRequiredExtensionConfig } from './types';
import { mergeElementProps, MlBaseFormListColumn } from '@/components/ml-base-form-list';

export type { CellRequiredExtensionConfig };

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

  return function (pipeline: Pipeline) {
    const columns = pipeline.getColumns();
    const globalEnable = config.enable ?? alwaysReturnTrue;
    const validatedState = pipeline.getStateAtKey('cellRequired') ?? [];
    const formListData = pipeline.getFormListData();

    const mappingFields = callable(config.mapping, { columns }).map((item) =>
      typeof item === 'string' ? item : item.field,
    );

    const safeMapping = new Map(
      callable(config.mapping, { columns })
        .map((item) =>
          typeof item === 'string'
            ? { field: item, enable: (row: any) => globalEnable(item, row, mappingFields) }
            : item,
        )
        .map((item) => [item.field, item]),
    );

    function processColumns(columns: MlBaseFormListColumn[]) {
      const dfs = (col: MlBaseFormListColumn): MlBaseFormListColumn => {
        const colField = col.field;

        return {
          ...col,
          getCellProps: (cellValue, row, opts) => {
            const prevProps = col.getCellProps?.(cellValue, row, opts) ?? {};

            const isRequiredError = validatedState.includes(`${opts.rowIndex}_${colField}`);
            const isRequired = safeMapping.get(colField)?.enable(row, opts.rowIndex, { formListData });

            return mergeElementProps(prevProps, {
              className: classNames(prevProps.className, {
                'mark-form-list-cell-required-error-indicator': isRequiredError,
                'mark-form-list-cell-required-star-indicator': !isRequiredError && isRequired,
              }),
            });
          },
        };
      };

      return columns.map(dfs);
    }

    pipeline.inputColumns(processColumns(columns));

    return pipeline;
  };
}
