import { useEffect, useState, forwardRef, useImperativeHandle } from 'react';
import {
  Box,
  Typography,
  TextField,
  Autocomplete
} from '@mui/material';
import useValidation, { MAX_NAME_LENGTH, ATTRIBUTE_NAME_PATTERN } from '../../../hooks/useValidation';
import { CmdbItem, getAutocompleteInventory } from '../../../store/cmdbSlice/thunks';
import { CMDB_ITEM_TYPES } from '../../../store/constants';
import { getFirstEntryName, getFirstEntryValue, getFirstEntryId, getFirstEntryHostkey } from '../../../utils';
import { useAutocompleteField } from '../../../hooks/useAutocompleteField';
import { useFormStyles } from '../styles';

interface InventoryAttributeFormProps {
  identifier: string;
  setCmdbItem: (item: CmdbItem) => void;
  item?: CmdbItem;
}

interface InventoryAttributeFormRef {
  validate: () => Promise<boolean>;
}


const InventoryAttributeForm = forwardRef<InventoryAttributeFormRef, InventoryAttributeFormProps>(
  ({ identifier, setCmdbItem, item }, ref) => {
    const { classes } = useFormStyles();
    const [name, setName] = useState<string>(getFirstEntryName(item));
    const [attributeName, setAttributeName] = useState<string | null>(item?.name || null);
    const [value, setValue] = useState<string>(getFirstEntryValue(item) || '');
    const [description, setDescription] = useState<string>(item?.description || '');
    const [tags, setTags] = useState<string[]>(item?.tags || []);

    const { options: inventoryOptions, loading: loadingInventory } = useAutocompleteField({
      query: attributeName || '',
      fetchThunk: getAutocompleteInventory
    });

    const { errors, validate } = useValidation({
      customRules: {
        attributeName: {
          required: true,
          maxLength: MAX_NAME_LENGTH,
          pattern: ATTRIBUTE_NAME_PATTERN,
          patternMessage: "Name can only contain letters, numbers, underscores and spaces.",
        }
      }
    });

    const validateForm = async (): Promise<boolean> => {
      const formItem: CmdbItem = {
        type: CMDB_ITEM_TYPES.INVENTORY,
        name: attributeName,
        attributeName,
        description,
        tags,
        entries: [{
          item_name: name,
          item_value: value,
          entry_id: item?.id,
          item_type: CMDB_ITEM_TYPES.VARIABLE,
          id: getFirstEntryId(item),
          hostkey: getFirstEntryHostkey(item)
        }]
      };

      return await validate({ item: formItem, identifier });
    };

    useImperativeHandle(ref, () => ({
      validate: validateForm,
    }), [validate, name, attributeName, value, description, tags, item, identifier]);

    useEffect(() => {
      const formItem: CmdbItem = {
        type: CMDB_ITEM_TYPES.INVENTORY,
        name: attributeName,
        description,
        tags,
        entries: [{
          item_name: name,
          item_value: value,
          item_type: "variable",
          id: getFirstEntryId(item),
          hostkey: getFirstEntryHostkey(item),
          entry_id: item?.id
        }]
      };

      setCmdbItem(formItem);
    }, [name, description, tags, value, attributeName, setCmdbItem, item]);

    useEffect(() => {
      if (attributeName !== null) return;

      const extractedName = tags.reduce((acc, tag) => {
        if (tag.includes("attribute_name=")) {
          return tag.replace("attribute_name=", "");
        }
        return acc;
      }, "");

      if (extractedName) {
        setAttributeName(extractedName);
      }
    }, [tags, attributeName]);

    useEffect(() => {
      if (attributeName) {
        setTags([CMDB_ITEM_TYPES.INVENTORY, `attribute_name=${attributeName}`]);
        setName(`data:variables.${attributeName.toLowerCase().replace(/\s+/g, '_')}`);
      }
    }, [attributeName]);

    return (
      <>
        <Box className={classes.formRow}>
          <Typography variant="body1" className={classes.label}>
            Name:
          </Typography>
          <Box className={classes.fieldContainer}>
            <Autocomplete
              freeSolo
              options={inventoryOptions}
              value={attributeName || ''}
              loading={loadingInventory}
              onInputChange={(_, newValue) => setAttributeName(newValue)}
              renderInput={(params) => (
                <TextField
                  {...params}
                  fullWidth
                  variant="outlined"
                  size="small"
                  placeholder="Attribute name"
                  error={!!errors.attributeName || !!errors.item_name}
                  helperText={errors.attributeName || errors.item_name}
                />
              )}
            />
          </Box>
        </Box>
        <Box className={classes.formRow}>
          <Typography variant="body1" className={classes.label}>
            Value:
          </Typography>
          <Box className={classes.fieldContainer}>
            <TextField
              fullWidth
              variant="outlined"
              size="small"
              placeholder="Value"
              value={value}
              onChange={(e) => setValue(e.target.value)}
              error={!!errors.item_value}
              helperText={errors.item_value}
            />
          </Box>
        </Box>
        <Box className={classes.descriptionRow}>
          <Typography variant="body1" className={classes.label}>
            Description:
          </Typography>
          <Box className={classes.fieldContainer}>
            <TextField
              variant="outlined"
              multiline
              fullWidth
              rows={3}
              placeholder="Description"
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              error={!!errors.description}
              helperText={errors.description}
            />
          </Box>
        </Box>
      </>
    );
  });

export default InventoryAttributeForm;
