import pandas as pd
import numpy as np
import sys
import os
import json
import argparse

# Add root to path to allow importing strategies
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

try:
    import strategies.strategy_activation_scores as strategy_module
except ImportError:
    print("Error: Could not import 'strategies.strategy_activation_scores'. Run this from the project root.")
    sys.exit(1)

def load_data(filepath):
    if not os.path.exists(filepath):
        print(f"Error: File not found: {filepath}")
        sys.exit(1)
    df = pd.read_csv(filepath)
    # Normalize columns
    df.columns = df.columns.str.lower().str.strip()
    if 'time' in df.columns:
        df['time'] = pd.to_datetime(df['time'])
    return df

def analyze_component(s_tv, s_py, name):
    """Calculates and prints statistics for a single component."""
    # Align and Compare
    common_len = min(len(s_tv), len(s_py))
    s_tv = s_tv.iloc[:common_len].fillna(0)
    s_py = s_py.iloc[:common_len].fillna(0)
    
    # Calculate diff
    diff = s_tv - s_py
    abs_diff = diff.abs()
    
    print(f"\n--- Analysis for '{name}' ---")
    if abs_diff.mean() < 1e-9 and s_tv.corr(s_py) > 0.999999:
        print("✅  PERFECT MATCH")
        return True

    print(f"  - Correlation: {s_tv.corr(s_py):.6f}")
    print(f"  - Mean Abs Diff: {abs_diff.mean():.6f}")
    print(f"  - Max Diff: {abs_diff.max():.6f}")
    
    # Show Top Discrepancies
    threshold = 0.001
    bad_rows = abs_diff[abs_diff > threshold]
    print(f"  - Rows with diff > {threshold}: {len(bad_rows)} / {common_len}")
    
    if len(bad_rows) > 0:
        print("  - Top 5 Discrepancies (by index):")
        top_indices = bad_rows.nlargest(5).index
        for idx in top_indices:
            print(f"    - Idx {idx}: TV={s_tv.iloc[idx]:.4f}, PY={s_py.iloc[idx]:.4f}, Diff={diff.iloc[idx]:.4f}")
    return False

def compare_components(df_tv, params_file=None):
    # 1. Get Python Scores
    params = {}
    if params_file and os.path.exists(params_file):
        print(f"Loading parameters from {params_file}...")
        try:
            if params_file.endswith('.json'):
                with open(params_file, 'r') as f:
                    data = json.load(f)
                    for k, v in data.items():
                        if isinstance(v, dict) and 'values' in v:
                            params[k] = v['values'][0]
                        elif isinstance(v, dict) and 'start' in v:
                            params[k] = v['start']
                        else:
                            params[k] = v
            elif params_file.endswith('.csv'):
                df_params = pd.read_csv(params_file)
                params = df_params.iloc[0].to_dict()
        except Exception as e:
            print(f"Error loading params: {e}")

    print("Generating Python signals and components...")
    try:
        # We assume generate_signals populates the dataframe with all component columns
        df_py = strategy_module.generate_signals(df_tv.copy(), **params)
    except Exception as e:
        print(f"Error running strategy: {e}")
        return

    # 2. Define component mappings
    # Mapping from Python name to TradingView name
    # Using the DB_ columns from the export as they are likely for debugging
    component_map = {
        'stoch_value': 'db_stoch',
        'macd_prediction': 'db_macd_pred',
        'osc_1d': 'db_osc',
        'm3_momentum': 'db_m3_mom',
        'm2_diff_abs_tinyoffset_to_future': 'db_m2_diff',
        'rsid_osc': 'db_rsid',
        'stoch_div_osc': 'db_stoch_div',
        'vwap_div_osc': 'db_vwap_div',
        'm3_div_osc': 'db_m3_div',
        'm2_div_osc': 'db_m2_div_tiny',
        'm2_div_osc_nooffset': 'db_m2_div_nooff',
        'bearish_engulfing_score': 'db_bearish',
        'activation_score': 'db_score', # Compare against the debug score
    }

    print("\nStarting Component-wise Analysis...")
    perfect_matches = 0
    mismatches = []
    
    for py_name, tv_name in component_map.items():
        if py_name not in df_py.columns:
            print(f"\n- Skipping '{py_name}': Not found in Python DataFrame.")
            continue
        if tv_name not in df_tv.columns:
            print(f"\n- Skipping '{tv_name}': Not found in TradingView Export.")
            continue
            
        is_match = analyze_component(df_tv[tv_name], df_py[py_name], py_name)
        if is_match:
            perfect_matches += 1
        else:
            mismatches.append(py_name)

    print("\n--- Summary ---")
    print(f"Total components checked: {len(component_map)}")
    print(f"Perfect matches: {perfect_matches}")
    print(f"Mismatched components: {len(mismatches)}")
    if mismatches:
        print("Mismatched component list:", mismatches)
        print("\nRecommendation: Start by investigating the first mismatched component in the list.")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Diagnose discrepancies between Python strategy and TradingView export.")
    parser.add_argument("--data", default="results/TV_Export.csv", help="Path to TradingView Export CSV file.")
    parser.add_argument("--params", default="optimization_winner_activation_scores.csv", help="Path to parameters CSV/JSON file.")
    args = parser.parse_args()
    
    df_tv_export = load_data(args.data)
    compare_components(df_tv_export, args.params)