"""metrics.py provides utility functions to simplify the process of 
retrieving metric results from measurement engine results.

This module includes functions to extract metric data from CSV files 
generated by measurement engines for individual runs or all runs in 
an experiment.
"""
import csv
import os
from typing import Union
from adgtk.tracking.structure import EXP_RESULTS_FOLDER

def get_single_run_metric_data(
    results_folder: str,
    engine_id: str,
    metric: str
) -> list:
    """
    Retrieve metric data for a single run from a CSV file.

    Args:
        results_folder (str): Path to the folder containing the results.
        engine_id (str): Identifier for the measurement engine.
        metric (str): Name of the metric to retrieve.

    Returns:
        list: A list of numeric values (int or float) representing the metric data. 
              Returns an empty list if the file does not exist or cannot be read.
    """
    meas_file = f"{engine_id}.{metric}.csv"
    file_w_path = os.path.join(results_folder, "metrics", meas_file)
    if not os.path.exists(file_w_path):
        return []
    data:list[Union[int, float]] = []
    try:
        with open(file_w_path, mode="r", encoding="utf-8") as infile:
            csv_reader = csv.reader(infile)
            for row in csv_reader:
                for entry in row:
                    try:
                        # Try converting to int first
                        data.append(int(entry))
                    except ValueError:
                        try:
                            # If int fails, try converting to float
                            data.append(float(entry))
                        except ValueError:
                            # Skip invalid entries
                            pass
    except (OSError, IOError):
        # Handle file read errors
        return []
    return data

def get_all_metric_data(experiment_name: str, engine_id: str, metric: str) -> dict:
    """
    Retrieve metric data for all runs in an experiment.

    Args:
        experiment_name (str): the name of the experiment.
        engine_id (str): Identifier for the measurement engine.
        metric (str): Name of the metric to retrieve.

    Returns:
        dict: A dictionary where keys are run folder names and values 
              are lists of numeric values (int or float) representing 
              the metric data for each run. Returns an empty dictionary 
              if no valid directories are found.
    """
    results = {}
    experiment_root = os.path.join(EXP_RESULTS_FOLDER, experiment_name)
    run_folders = [folder for folder in os.listdir(experiment_root) 
                   if os.path.isdir(os.path.join(experiment_root, folder))]
    for folder in run_folders:
        folder_w_path = os.path.join(experiment_root, folder)
        results[folder] = get_single_run_metric_data(
            results_folder=folder_w_path,
            engine_id=engine_id,
            metric=metric)
    return results