import pandas as pd
import logging
import numpy as np
from prophet import Prophet
import warnings
import os
import sys
from contextlib import contextmanager

warnings.filterwarnings("ignore")

# --- ADD THIS HELPER ---
@contextmanager
def suppress_stdout_stderr():
    """Redirects stdout and stderr to devnull to silence C++ logs."""
    with open(os.devnull, 'w') as fnull:
        old_stdout, old_stderr = sys.stdout, sys.stderr
        sys.stdout, sys.stderr = fnull, fnull
        try:
            yield
        finally:
            sys.stdout, sys.stderr = old_stdout, old_stderr

def detect_time_series_anomalies_fb_walkforward(
    group,
    variable,
    date_column,
    eval_period,
    interval_width
):
    # 1. Silence the cmdstanpy logger completely
    logger = logging.getLogger('cmdstanpy')
    logger.addHandler(logging.NullHandler())
    logger.propagate = False
    logger.setLevel(logging.CRITICAL) # Only show critical errors
    
    group = group.sort_values(date_column).copy()
    group[date_column] = pd.to_datetime(group[date_column])

    cutoff_date = group[date_column].max() - pd.Timedelta(weeks=eval_period)

    group["FB_forecast"] = np.nan
    group["FB_low"] = np.nan
    group["FB_high"] = np.nan

    train = group[group[date_column] <= cutoff_date].copy()
    test = group[group[date_column] > cutoff_date].copy()

    for i, row in test.iterrows():
        prophet_train = train.rename(columns={date_column: "ds", variable: "y"})

        try:
            model = Prophet(
                weekly_seasonality=True,
                yearly_seasonality=True,
                daily_seasonality=False,
                interval_width=interval_width
            )
            
            # --- WRAP THE FIT IN THE MUTER ---
            with suppress_stdout_stderr():
                model.fit(prophet_train)

            future = pd.DataFrame({"ds": [row[date_column]]})
            fc = model.predict(future).iloc[0]

            group.loc[i, "FB_forecast"] = fc["yhat"]
            group.loc[i, "FB_low"] = max(fc["yhat_lower"], 0)
            group.loc[i, "FB_high"] = fc["yhat_upper"]

        except Exception as e:
            # Note: We don't mute this so you can still see actual errors
            print(f"Prophet failed for KEY={group['key'].iloc[0]} on date={row[date_column]}: {e}")
            group.loc[i, "FB_forecast"] = train[variable].iloc[-1]
            group.loc[i, "FB_low"] = max(train[variable].iloc[-1], 0)
            group.loc[i, "FB_high"] = train[variable].iloc[-1]

        new_train_row = row.to_frame().T
        train = pd.concat([train, new_train_row], ignore_index=True)

    group["FB_residual"] = group[variable] - group["FB_forecast"]
    group["FB_anomaly"] = np.nan
    mask = group[date_column] > cutoff_date

    group.loc[mask & (group[variable] > group["FB_high"]), "FB_anomaly"] = "high"
    group.loc[mask & (group[variable] < group["FB_low"]), "FB_anomaly"] = "low"

    group["is_FB_anomaly"] = group["FB_anomaly"].notna()
    
    train_mask = group[date_column] <= cutoff_date
    group.loc[train_mask, "FB_residual"] = np.nan
    group.loc[train_mask, "is_FB_anomaly"] = np.nan

    return group