import { FileField } from '@/components/ra-fields';
import { LabeledInput } from '@/components/ra-inputs/LabeledInput';
import { styled } from '@mui/material/styles';
import { get } from 'lodash';
import React, { useMemo } from 'react';
import { FileInput as RaFileInput, FileInputProps as RaFileInputProps, useRecordContext } from 'react-admin';
import { useWatch } from 'react-hook-form';

const StyledFileInput = styled(RaFileInput, { slot: 'root' })(({ theme }) => ({
  '& .previews': {},
  '& .previews>div': {
    marginTop: theme.spacing(1),
    padding: theme.spacing(1.5),
    border: `1px solid ${theme.palette.divider}`,
    borderRadius: theme.shape.borderRadius,
    '& button': {
      float: 'right',
      placeItems: 'flex-end',
      verticalAlign: 'middle'
    },
    '&:hover': {
      backgroundColor: theme.palette.action.hover
    },
    '& .MuiLink-root': {
      fontSize: theme.typography.body1.fontSize
    }
  }
}));

/**
 * FileInput is designed to be used as single input. It does not support multiple files and
 * can be used only for base64 encoded files using applica framework.
 *
 * @example
 * // If you hav an object class with @File annotation, you can map it to a FileInput:
 * ...
 * <FileInput source="file_property" />
 *
 * The component will handle create and delete operations related to the source field associated
 * in conjuction with Applica Framework backend API services.
 *
 */
function FileInput({ children = <FileField source="" title="" />, title, ...props }: FileInputProps): JSX.Element {
  const file = useWatch({ name: props.source });
  const record = useRecordContext(props);
  const { source } = props;
  // Base64 files are persisted with a simple string that contains the temporary filename.
  // Applica Framework add a suffix to the temporary filename that is the original filename.
  // With a little trick we try (because we are not sure that this is true) to get the original filename.
  const filename = useMemo(() => {
    if (file && file?.title) {
      return file?.title;
    }
    const filename = get(record, source);
    if (filename) {
      const parts = filename.split('__');
      return parts.length > 0 ? parts[parts.length - 1] : filename;
    }
    return filename;
  }, [record, source, file]);

  return (
    // @ts-ignore
    <LabeledInput {...props}>
      {/* @ts-ignore */}
      <StyledFileInput>
        {
          /** @ts-ignore */
          React.cloneElement(children, {
            // @ts-ignore
            ...children.props,
            title: title || source,
            source,
            record: {
              ...record,
              [source]: file?.title || get(record, source),
              [`_${source}`]: file?.src || get(record, `_${source}`),
              [title || source]: filename
            }
          })
        }
      </StyledFileInput>
    </LabeledInput>
  );
}

type FileInputProps = {
  source: string;
  title?: string;
  children?: React.ReactNode;
} & RaFileInputProps;

export { FileInput };
export type { FileInputProps };
