import os
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from abc import ABC, abstractmethod

from .base import BaseAnalysis
from app.analysis.data_utils import prepare_data, mk_plotdir

import matplotlib
matplotlib.use('Agg')

# -------------------------------------------
# Base Class for All Plot Analyses
# -------------------------------------------
class BasePlotAnalysis(BaseAnalysis, ABC):
    """
    Base class for all plot-based analyses.
    It enforces a structure for:
    - Data preparation
    - Transformation
    - Plot generation
    - Memory cleanup

    Attributes:
    plot_filename (str): The filename for the output plot.
    alt_text (str): The alt text for the plot.
    """
    plot_filename = "default_plot.png"
    alt_text = "Default Alt Text"

    def execute(self, df: pd.DataFrame):
        """
        Executes the full analysis pipeline.

        Parameters:
        df (pd.DataFrame): The input DataFrame containing user activity data.

        Returns:
        str: HTML img tag containing the URL to the generated plot.
        """
        df = prepare_data(df)  # Step 1: Prepare data

        paths = mk_plotdir(self.plot_filename)
        self.output_path, self.plot_url = paths['output_path'], paths['plot_url']

        df = self.transform_data(df)  # Step 2: Transform data (implemented by subclass)
        self.plot_data(df)  # Step 3: Create the plot

        plt.savefig(self.output_path, bbox_inches="tight")
        plt.close()
        
        del df  # Step 4: Free memory
        return f'<img src="{self.plot_url}" alt="{self.note}">'

    @abstractmethod
    def transform_data(self, df: pd.DataFrame) -> pd.DataFrame:
        """
        Subclasses must define how they transform the data.

        Parameters:
        df (pd.DataFrame): The input DataFrame containing user activity data.

        Returns:
        pd.DataFrame: The transformed DataFrame.
        """
        pass

    @abstractmethod
    def plot_data(self, df: pd.DataFrame):
        """
        Subclasses must define how they generate the plot.

        Parameters:
        df (pd.DataFrame): The transformed DataFrame containing data to be plotted.
        """
        pass