from .contribution import compute_contribution
from .growth import compute_growth
from .rate import compute_rate
from .trend import compute_trend


def compute_metrics(df, schema):
    metrics = []

    time_cols = schema.time
    metric_cols = schema.metrics
    dimension_cols = schema.dimensions
    flag_cols = schema.flags
    time_col = pick_best_time_column(df, time_cols)
    work_df = df

    # Fallback for non-temporal datasets: use row order as pseudo-time.
    if not time_col and metric_cols:
        work_df = df.copy()
        work_df["_row_order"] = range(1, len(work_df) + 1)
        time_col = "_row_order"

    # Growth metrics
    if time_col:
        for metric_col in metric_cols:
            metrics += compute_growth(work_df, time_col, metric_col)

    # Trend metrics
    if time_col:
        for metric_col in metric_cols:
            # Group by time to get a time-series for trend analysis
            series = work_df.groupby(time_col)[metric_col].sum().sort_index()
            metrics += compute_trend(series, metric_col)

    # Contribution metrics
    for metric_col in metric_cols:
        for dim_col in dimension_cols:
            metrics += compute_contribution(df, metric_col, dim_col)

    # Rate metrics
    for flag_col in flag_cols:
        if time_col:
            metrics += compute_rate(df, time_col, flag_col)

    return metrics


def pick_best_time_column(df, time_cols):
    if not time_cols:
        return None

    # 1) Prefer a true datetime column.
    for col in time_cols:
        if col in df.columns and df[col].dtype.kind == "M":
            return col

    # 2) Prefer common date-like names.
    preferred_name_tokens = ("report", "date", "time", "period")
    for col in time_cols:
        name = col.lower()
        if any(token in name for token in preferred_name_tokens):
            return col

    # 3) Fallback: column with most distinct values.
    best_col = None
    best_uniques = -1
    for col in time_cols:
        if col not in df.columns:
            continue
        uniques = df[col].nunique(dropna=True)
        if uniques > best_uniques:
            best_uniques = uniques
            best_col = col

    return best_col


def _pick_best_time_column(df, time_cols):
    # Backward compatibility for internal callers.
    return pick_best_time_column(df, time_cols)
