import pandas as pd
import ipywidgets as widgets
from IPython.display import display, clear_output, Markdown
from IPython import get_ipython
from .main import timeseries_anomaly_detection


def anomaly_detection_guide():
    """
    Master workflow function that orchestrates:
    1. Selection of the Dataframe
    2. Configuration of Columns & Globals setting
    """
    
    run_msg = """
<span style="background-color: ghostwhite; padding: 2px 6px; border-radius: 4px; font-family: monospace;">
    run_anomaly_detection()
</span>
"""
    ns = get_ipython().user_ns
    
    # --- OUTPUT CONTAINERS ---
    step1_output = widgets.Output()
    step2_output = widgets.Output()
    step3_output = widgets.Output() # Will just hold the final print statement
    
    display(step1_output)
    display(step2_output)
    display(step3_output)

    # =========================================================================
    # STEP 1: SELECT DATAFRAME
    # =========================================================================
    with step1_output:
        active_dfs = [
            name for name, obj in ns.items() 
            if isinstance(obj, pd.DataFrame) 
            and not name.startswith('_') 
            and len(obj) >= 52
        ]
        
        if not active_dfs:
            print("❌ No DataFrames found with at least 52 rows.")
            return

        initial_df = active_dfs[0]
        
        dd_df = widgets.Dropdown(
            options=active_dfs, value=initial_df,
            description='DataFrame:', style={'description_width': 'initial'},
            layout={'width': '300px'}
        )
        
        btn_df = widgets.Button(
            description=f"Set '{initial_df}' as master_data?", 
            button_style='primary', icon='check', layout={'width': '400px'}
        )
        
        out_df_preview = widgets.Output()
        
        def update_df_preview(change):
            if change['new']:
                btn_df.description = f"Set '{change['new']}' as master_data!"
                with out_df_preview:
                    clear_output()
                    sel_df = ns[change['new']]
                    print(f"📄 Preview ({len(sel_df)} rows):")
                    display(sel_df.head(3))
        
        dd_df.observe(update_df_preview, names='value')
        
        with out_df_preview:
            print(f"📄 Preview ({len(ns[initial_df])} rows):")
            display(ns[initial_df].head(3))

        display(widgets.VBox([
            widgets.HTML("<h3>Step 1: Select Input DataFrame</h3>"),
            dd_df, btn_df, out_df_preview,
            widgets.HTML("<hr>")
        ]))

    # =========================================================================
    # LOGIC: TRANSITION TO STEP 2
    # =========================================================================
    def load_step_2(b):
        selected_name = dd_df.value
        # We temporarily store this to load columns, but final global set happens in Save
        temp_df = ns[selected_name].copy()
        
        step2_output.clear_output()
        step3_output.clear_output()
        
        with step2_output:
            print(f"✅ Selected '{selected_name}'. Loading Column Options...")
            
            # --- ANALYZE COLUMNS ---
            all_cols = temp_df.columns.tolist()
            
            def date_priority(col_name):
                if pd.api.types.is_datetime64_any_dtype(temp_df[col_name]): return 0 
                if any(x in col_name.lower() for x in ['date', 'time', 'ds', 'ts', 'week']): return 1
                if not pd.api.types.is_numeric_dtype(temp_df[col_name]): return 2
                return 3
            sorted_dates = sorted(all_cols, key=date_priority)
            
            numeric_cols = temp_df.select_dtypes(include=['number']).columns.tolist()
            numeric_cols.reverse()
            
            group_candidates = temp_df.select_dtypes(exclude=['number']).columns.tolist()

            # --- STEP 2 WIDGETS ---
            w_group = widgets.SelectMultiple(
                options=group_candidates,
                rows=6,
                style={'description_width': 'initial'}, layout={'width': '350px'}
            )
            w_date = widgets.Dropdown(
                options=sorted_dates,
                style={'description_width': 'initial'}, layout={'width': '350px'}
            )
            w_target = widgets.Dropdown(
                options=numeric_cols,
                style={'description_width': 'initial'}, layout={'width': '350px'}
            )
            w_eval = widgets.BoundedIntText(
                value=1, min=1, max=1000,
                style={'description_width': 'initial'}, layout={'width': '150px'}
            )
            btn_save_cfg = widgets.Button(
                description="Save Configuration", button_style='primary', 
                icon='save', layout={'width': '350px'}
            )
            out_cfg_status = widgets.Output()

            def on_date_change(change):
                new_date = change['new']
                w_group.options = [c for c in group_candidates if c != new_date]
            w_date.observe(on_date_change, names='value')
            on_date_change({'new': w_date.value})

            display(widgets.VBox([
                widgets.HTML("<h3>Step 2: Configure Detection Parameters</h3>"),
                widgets.HTML("<b>A. Select Unique ID Columns (Ctrl/Cmd for multiple):</b>"), w_group,
                widgets.HTML("<b>B. Select Date Column:</b>"), w_date,
                widgets.HTML("<b>C. Select Target Variable:</b>"), w_target,
                widgets.HTML("<b>D. Trailing records to evaluate:</b>"), w_eval,
                widgets.HTML("<br>"), btn_save_cfg, out_cfg_status,
                widgets.HTML("<hr>")
            ]))

            # =================================================================
            # LOGIC: SAVE GLOBALS (Replaces Step 3 Transition)
            # =================================================================
            def save_globals(b):
                # 1. Set the specific global variables you requested
                ns['master_data'] = temp_df  # The dataframe
                ns['unique_ids'] = list(w_group.value) # The grouping columns
                ns['date_column'] = w_date.value
                ns['variable'] = w_target.value
                ns['eval_period'] = w_eval.value
                
                # Feedback in Step 2 container
                with out_cfg_status:
                    clear_output()
                    print("✅ Configuration Saved to Global Variables:")
                    print(f"   master_data ({len(ns['master_data'])} rows, {len(ns['master_data'][ns['unique_ids']].drop_duplicates())} unique_id count)")
                    print(f"   unique_ids: {ns['unique_ids']}")
                    print(f"   date_column: {ns['date_column']}")
                    print(f"   variable: {ns['variable']}")
                    print(f"   eval_period: {ns['eval_period']}")

                # 2. Print the run command in the "Step 3" output area
                step3_output.clear_output()
                with step3_output:
                    print("\nCopy and paste the command below into another cell and run:\n")
                    display(Markdown(run_msg))
                    print("")

            btn_save_cfg.on_click(save_globals)

    btn_df.on_click(load_step_2)



def run_anomaly_detection():
        ns = get_ipython().user_ns
        timeseries_anomaly_detection(
        master_data = ns['master_data'],
        unique_ids=ns['unique_ids'],
        date_column=ns['date_column'],
        variable=ns['variable'],
        eval_period=ns['eval_period'],
        )
    