import os
from typing import Tuple, Optional

import numpy as np
import pandas as pd

def extract_layer_data(
    relative_humidity_df: pd.DataFrame,
    thickness_df: pd.DataFrame,
    concentration_df: pd.DataFrame,
    layer_number: Optional[int] = None,
    aerosol_name: Optional[str] = None,
    time_resolution: Optional[str] = None,
    ) -> Tuple[pd.Series, pd.Series, pd.Series]:

    """
    Extracts data for a specific layer or aerosol based on the provided inputs.

    Args:
        relative_humidity_df (pd.DataFrame): DataFrame with columns for relative humidity.
        thickness_df (pd.DataFrame): DataFrame with columns for thickness.
        concentration_df (pd.DataFrame): DataFrame with columns for aerosol concentration.
        layer_number (Optional[int]): Layer number to extract (e.g., 1 for "layer_1"). Defaults to None.
        aerosol_name (Optional[str]): Name of the aerosol to extract (e.g., "brc"). Defaults to None.
        time_resolution (Optional[str]): Time resolution for resampling. Options: 'D' (daily), 'M' (monthly),
                                        'H' (hourly), or None (no resampling). Defaults to None.
    Returns:
        tuple: Three renamed Series ('RH', 'Thickness', 'aerosol_name') for the specified layer or aerosol.

    Raises:
        ValueError: If neither `layer_number` nor `aerosol_name` is provided, or if the specified layer/aerosol is not found.
    """

    layer = f"layer_{layer_number}"

    # Validate that the layer exists in all DataFrames
    if layer not in relative_humidity_df.columns or layer not in thickness_df.columns or layer not in concentration_df.columns:
        raise ValueError(f"The layer {layer} is not in the DataFrame.")

        # Extract and rename the columns
    relative_humidity = relative_humidity_df[layer].rename('RH')
    thickness = thickness_df[layer].rename('Thickness')
    concentration = concentration_df[layer].rename(aerosol_name.lower())

    # Handle time resolution if specified
    if time_resolution is not None:
        if time_resolution.upper() not in ['D', 'M', 'H']:
            raise ValueError("Invalid time_resolution. Options: 'D' (daily), 'M' (monthly), 'H' (hourly).")

        # Resample the data based on the time resolution
        relative_humidity = relative_humidity.resample(time_resolution).mean()
        thickness = thickness.resample(time_resolution).mean()
        concentration = concentration.resample(time_resolution).mean()
    
    return relative_humidity, thickness, concentration


def extract_target_layer_data(
    relative_humidity_df: pd.DataFrame,
    concentration_df: pd.DataFrame,
    target_layer: Optional[int] = None,
    aerosol_name: Optional[str] = None,
    time_resolution: Optional[str] = None,
    ) -> Tuple[pd.Series, pd.Series]:

    """
    Extracts data for a specific layer or aerosol based on the provided inputs.

    Args:
        relative_humidity_df (pd.DataFrame): DataFrame with columns for relative humidity.
        concentration_df (pd.DataFrame): DataFrame with columns for aerosol concentration.
        target_layer (Optional[int]): Layer number to extract (e.g., 1 for "layer_1"). Defaults to None.
        aerosol_name (Optional[str]): Name of the aerosol to extract (e.g., "brc"). Defaults to None.
        time_resolution (Optional[str]): Time resolution for resampling. Options: 'D' (daily), 'M' (monthly),
                                        'H' (hourly), or None (no resampling). Defaults to None.
    Returns:    
        tuple: Two renamed Series ('RH', 'aerosol_name') for the specified layer or aerosol.

    Raises:
        ValueError: If neither `target_layer` nor `aerosol_name` is provided, or if the specified layer/aerosol is not found.
    """

    layer_column = f"layer_{target_layer}"
    # Validate that the target layer exists in the input DataFrames
    if layer_column not in relative_humidity_df.columns:
        raise ValueError(f"Target layer {layer_column} not found in relative_humidity_df.")
    if layer_column not in concentration_df.columns:
        raise ValueError(f"Target layer {layer_column} not found in concentration_df.")

    # extract the data for the target layer
    relative_humidity = relative_humidity_df[layer_column].rename('RH')
    concentration = concentration_df[layer_column].rename(aerosol_name.lower())

    # Handle time resolution if specified
    if time_resolution is not None:
        if time_resolution.upper() not in ['D', 'M', 'H']:
            raise ValueError("Invalid time_resolution. Options: 'D' (daily), 'M' (monthly), 'H' (hourly).")

        # Resample the data based on the time resolution
        relative_humidity = relative_humidity.resample(time_resolution).mean()
        concentration = concentration.resample(time_resolution).mean()

    return relative_humidity, concentration