import { VevProps } from '@vev/utils';
import React, { useEffect, useState } from 'react';
import { SilkeFormProps } from '../silke-form';
import { SilkeSchemaField } from './silke-schema-field';
import { SilkeBox } from '../silke-box';
import { isFunction } from 'lodash';
import { useSchemaContext } from './silke-schema-context';

type SilkeSchemaFieldsProps<T extends { [key: string]: any }> = {
  schema: VevProps[];
  noPad?: boolean;
  row?: boolean;
  disabled?: boolean;
  readonly?: boolean;
  itemIndex?: number;
} & SilkeFormProps<T>;

export function SilkeSchemaFields<T extends { [key: string]: any }>(
  props: SilkeSchemaFieldsProps<T>,
) {
  const { schema = [], row, ...rest } = props;
  const context = useSchemaContext();
  const [filteredSchema, setFilteredSchema] = useState(schema);

  // Filter hidden fields here, so they don't use any space in the sidebar
  useEffect(() => {
    const ctxWithValue = { ...context, value: rest?.value ?? context.value };
    const isHidden = async (field: VevProps) => {
      if (isFunction(field?.hidden)) {
        return await field?.hidden(ctxWithValue, rest?.itemIndex);
      } else if (field?.hidden) {
        return true;
      }

      return false;
    };

    Promise.all(
      schema.map(async (field) => {
        const hidden = await isHidden(field);
        return hidden ? null : field;
      }),
    ).then((value) => {
      const filtered = value.filter((field) => {
        return field !== null;
      }) as VevProps[];
      setFilteredSchema(filtered);
    });
  }, [context, schema, rest?.itemIndex, rest?.value]);

  return (
    <SilkeBox flex column={!row} gap="s" vPad={row ? undefined : 's'} vAlign={row ? 'end' : undefined} style={{ width: '100%' }}>
      {filteredSchema.map((field, index) => {
        return (
          <span
            key={(field?.name || 'field') + index}
            style={field?.flex ? { flex: 1, minWidth: 0 } : undefined}
          >
            <SilkeSchemaField field={field} {...rest} isFirst={index === 0} />
          </span>
        );
      })}
    </SilkeBox>
  );
}
