/* eslint-disable react/prop-types */
import React, { useEffect, useRef, useState } from 'react';
import Image from 'next/image';
import { useTheme } from '@mui/material/styles';
import { DeleteRounded, ImageRounded, UploadRounded } from '@mui/icons-material';

import { CircularProgress, IconButton, Stack, Typography } from '@/mui/components';

import styles from './FormImageUploader.module.scss';

/**
 * FormImageUploader Component
 *
 * A component for uploading and displaying images with validation, error handling, and loading state.
 *
 * Props:
 * @param {object} props - Component properties.
 * @param {string} props.image - Initial image URL or data URI to be displayed.
 * @param {function} props.onRemove - Function to validate the uploaded file. Should
 * @param {function} props.onValidate - Function to validate the uploaded file
 * @param {function} props.onValidateAsync - Function to validate the uploaded file async
 * return true if valid, false otherwise. Function signature: (file: File) => boolean
 * @param {function} props.onLoad - Function to handle the loaded image data.
 * Function signature: (imageData: string, file: File) => void
 * @param {function} props.onError - Function to handle errors during file reading.
 * Function signature: (error: Event, file: File) => void
 * @param {string|undefined} props.backgroundColor - Background color of the image wrapper.
 * @param {string} props.accept - File types to accept in the file input (e.g., 'image/jpeg, image/png').
 * @param {string} props.restrictionMessage - Message restriction.
 * @param {boolean} props.readOnly
 * @param {boolean} props.disabled
 * @param {number} props.imageWidth - default 120px
 * @param {number} props.imageHeight - default 120px
 *
 * Usage:
 * ```jsx
 * <FormImageUploader
 *   disabled={false}
 *   readOnly={false}
 *   image={initialImage}
 *   onRemove={onRemove}
 *   onValidate={validateFile}
 *   onLoad={handleImageLoad}
 *   onError={handleImageError}
 *   backgroundColor="#ff0000"
 *   accept="image/jpeg, image/png"
 * />
 * ```
 */
function FormImageUploader(props) {
  const theme = useTheme();
  const [isLoading, setLoadingState] = useState(false);
  const inputRef = useRef(null);
  const [image, setImage] = useState(props.image);

  const imageWidth = props.imageWidth ?? 120;
  const imageHeight = props.imageHeight ?? 120;

  const clearInput = () => {
    inputRef.current.value = '';
    setImage('');
  };

  const readFile = async (event) => {
    const [file] = event.target.files;
    const isValid = props.onValidateAsync ? await props.onValidateAsync(file) : props.onValidate(file);

    if (!isValid) {
      inputRef.current.value = '';
    }

    if (file && isValid) {
      setLoadingState(true);

      const readerUrl = new FileReader();

      readerUrl.addEventListener('load', () => {
        setLoadingState(false);
        setImage(readerUrl.result);

        props.onLoad(event, file, readerUrl.result);
      });

      readerUrl.addEventListener('error', (error) => {
        setLoadingState(false);
        clearInput();

        props.onError(event, file, error);
      });

      readerUrl.readAsDataURL(file);
    }
  };

  useEffect(() => {
    setImage(props.image);
  }, [props.image]);

  const backgroundColor = props.backgroundColor ?? theme.palette.background.paper;

  return (
    <Stack direction="row" alignItems="flex-start" justifyContent="flex-start" fullWidth spacing={2}>
      <div>
        <div
          className={styles.ImageWrapper}
          style={{
            backgroundColor,
          }}
        >
          {isLoading && (
            <CircularProgress
              size="xLarge"
              color="neutral"
              style={{
                color: theme.palette.getContrastText(backgroundColor),
              }}
            />
          )}
          {!isLoading && image && (
            <Image className={styles.Image} src={image} alt="" width={imageWidth} height={imageHeight} />
          )}
          {!isLoading && !image && (
            <ImageRounded
              fontSize="xLarge"
              htmlColor={backgroundColor ? theme.palette.getContrastText(backgroundColor) : '#000000'}
            />
          )}
        </div>
      </div>
      <Stack spacing={2}>
        {!props.readOnly && (
          <Stack direction="row" alignItems="flex-start" spacing={1} className={styles.ControllerWrapper}>
            <IconButton size="small" color="neutral" component="label" disabled={props.disabled}>
              <UploadRounded />
              <input accept={props.accept} multiple={false} hidden type="file" ref={inputRef} onChange={readFile} />
            </IconButton>
            {image && (
              <IconButton
                size="small"
                color="neutral"
                onClick={() => {
                  clearInput();

                  props.onRemove?.();
                }}
                disabled={props.disabled}
              >
                <DeleteRounded />
              </IconButton>
            )}
          </Stack>
        )}
        <Typography variant="caption" color="text.secondary" whiteSpace="pre-wrap">
          {props.restrictionMessage}
        </Typography>
      </Stack>
    </Stack>
  );
}

export default FormImageUploader;
