input: from typing import List
  
  def sentiment_analysis(reviews: pd.DataFrame) -> pd.DataFrame:
      """ Perform sentiment analysis on a dataframe of product reviews. The function will tokenize the reviews, 
      remove stopwords, normalize the words, and generate features using a CountVectorizer. It will then split 
      the data into training and test sets, train a Multinomial Naive Bayes model, and generate a classification 
      report on the test set.
      >>> data = pd.DataFrame({
      ...     'review': ['This product is amazing!', 'I hate this product'],
      ...     'sentiment': ['positive', 'negative']
      ... })
      >>> result = sentiment_analysis(data)
      >>> print(result)
        precision    recall  f1-score   support
      <BLANKLINE>
        negative       1.00      1.00      1.00         1
        positive       1.00      1.00      1.00         1
      <BLANKLINE>
      accuracy                           1.00         2
      macro avg       1.00      1.00      1.00         2
      weighted avg    1.00      1.00      1.00         2
      <BLANKLINE>
      """
      from nltk.tokenize import word_tokenize
      from nltk.corpus import stopwords
      from nltk.stem import WordNetLemmatizer
      from sklearn.feature_extraction.text import CountVectorizer
      from sklearn.model_selection import train_test_split
      from sklearn.naive_bayes import MultinomialNB
      from sklearn.metrics import classification_report
  
      # Tokenize the texts
      reviews['tokenised'] = reviews['review'].apply(word_tokenize)
  
      # Remove stopwords
      stop_words = set(stopwords.words('english'))
      reviews['filtered'] = reviews['tokenised'].apply(lambda x: [val for val in x if val not in stop_words])
  
      # Normalize words
      wordnet_lemmatizer = WordNetLemmatizer()
      reviews['normalised'] = reviews['filtered'].apply(lambda x: [wordnet_lemmatizer.lemmatize(val) for val in x])
  
      # Generate features using CountVectorizer
      cv = CountVectorizer()
      reviews['features'] = cv.fit_transform(reviews['normalised'].astype('str')).toarray()
  
      # Split into training and test sets
      X = reviews['features']
      y = reviews['sentiment']
      X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
  
      # Train model
      model = MultinomialNB(alpha=0.1)
      model.fit(X_train, y_train)
  
      # Predict using the test set
      predictions = model.predict(X_test)
  
      # Generate a classification report
      report = classification_report(y_test, predictions)
      return report
output:     
      # Convert report to DataFrame for better presentation
      from io import StringIO
      import pandas as pd
  
      report_df = pd.read_csv(StringIO(report), sep='\s+')
      return report_df
  