import { getClassNames } from '@websolutespa/bom-core';
import { FormArray, FormGroup, FormValue } from '@websolutespa/bom-mixer-forms';
import { useLabel } from '@websolutespa/bom-mixer-hooks';
import { forwardRef, useEffect, useState } from 'react';
import styled from 'styled-components';
import { Button, Flex, Text, UIStyledComponentProps, UIStyledComponentPropsWithRef } from '../../components';
import { getCssResponsive } from '../../components/utils';
import { getVariant, useVariants } from '../../variants';
import { IFormTesterVariants, formTesterVariants } from './form-tester.variants';
import { useFormTester } from './useFormTester';

type VariantProps = UIStyledComponentProps<{
  variant?: keyof typeof formTesterVariants | (string & {});
  variants?: IFormTesterVariants;
}, 'div'>;

type ComponentProps<T extends Record<string, FormValue> | FormValue[] = Record<string, FormValue> | FormValue[]> = {
  test: T;
  form: FormGroup | FormArray;
  onTest?: () => void;
  onReset?: () => void;
};

type Props<T extends Record<string, FormValue> | FormValue[] = Record<string, FormValue> | FormValue[]> = ComponentProps<T> & VariantProps;

export type FormTesterProps = UIStyledComponentProps<ComponentProps, 'div'>;

export type FormTesterComponent<C extends React.ElementType = 'div'> =
  <T extends Record<string, FormValue> | FormValue[] = Record<string, FormValue> | FormValue[]>(
    props: UIStyledComponentPropsWithRef<C, Props<T>>
  ) => any & { displayName?: string };

const StyledFormTester = styled.div<VariantProps>`
  ${props => getVariant(props.variant, props.variants)}
  ${props => getCssResponsive(props)}
`;

export const FormTester: FormTesterComponent = forwardRef(
  function FormTester({
    className,
    form,
    test,
    variant = 'default',
    variants,
    ...props
  }, ref) {
    const label = useLabel();
    const globalVariants = useVariants('formTester', formTesterVariants);
    variants = variants || globalVariants;
    const [json, setJson] = useState(form ? JSON.stringify(form.value, null, 2) : null);
    useEffect(() => {
      const onChange = (value: any) => {
        // console.log('FormTesterComponent.onChange', value);
        setJson(JSON.stringify(value, null, 2));
      };
      form.on('change', onChange);
      return () => form.off('change', onChange);
    }, [form]);
    const onReset = () => {
      form.reset();
      props.onReset && props.onReset();
    };
    const onTest = () => {
      form.patch(test);
      props.onTest && props.onTest();
    };
    const classNames = getClassNames('input', className, variant);
    const { enabled } = useFormTester();
    if (!enabled) {
      return null;
    }
    return (
      <StyledFormTester ref={ref} className={classNames} variant={variant} variants={variants} {...props}>
        <Flex.Col gap="1rem">
          <Flex.Col>
            <Text variant="paragraph10" fontWeight="700">Form Tester</Text>
            <Text variant="paragraph30" lineHeight="1.3">this component is only visible during development.</Text>
          </Flex.Col>
          {json && (
            <code>{json}</code>
          )}
          <Flex.Row className="actions" justifyContent="space-between">
            <Flex>
              <Button variant="outline" size="sm" onClick={() => onReset()}>{label('form.reset')}</Button>
            </Flex>
            <Flex>
              <Button variant="primary" size="sm" onClick={() => onTest()}>{label('form.test')}</Button>
            </Flex>
          </Flex.Row>
        </Flex.Col>
      </StyledFormTester>
    );
  }
);
