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

import { mergeCellProps } from '@/components/ml-base-form';

import type { Pipeline } from '../pipeline';
import type { CellRequiredConfig } from './types';
import type { MlBaseFormColumn } from '@/components/ml-base-form';

export type { CellRequiredConfig };

export function cellRequired(config?: CellRequiredConfig) {
  if (config === null || config === undefined) {
    return (pipeline: Pipeline) => pipeline;
  }

  return function (pipeline: Pipeline) {
    const columns = pipeline.getColumns();
    const validateResult = pipeline.getStateAtKey('cellRequired') ?? [];
    const mapping = config.mapping;

    function processColumns(columns: MlBaseFormColumn[]) {
      return columns.map((item) => {
        const colField = item.field;
        const requiredFn = mapping[colField] ?? alwaysReturnFalse;

        const getCellProps = item.getCellProps;
        const getHeaderProps = item.getHeaderProps;

        const nextCol: typeof item = {
          ...item,
          getHeaderProps: (cellValue, formData) => {
            const prevProps = getHeaderProps?.(cellValue, formData) ?? {};

            if (callable(requiredFn, formData)) {
              return mergeCellProps(prevProps, {
                className: classNames(
                  prevProps.className,
                  "before:content-['*'] before:font-bold before:text-[1.2rem] before:absolute before:left-[-0.6rem] before:top-1/2 before:transform before:-translate-y-1/3 before:text-[#ff0033] before:pointer-events-none",
                ),
              });
            }

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

            if (validateResult.includes(colField)) {
              return mergeCellProps(prevProps, {
                className: classNames(prevProps.className, 'is-error'),
              });
            }

            return prevProps;
          },
        };

        return nextCol;
      });
    }

    pipeline.inputColumns(processColumns(columns));

    return pipeline;
  };
}
