from flask import Flask, render_template,request, jsonify
from datetime import datetime, timedelta
from engine import DataEngine, StrategyEngine
import concurrent.futures
from flask_caching import Cache
import csv, os, logging
from concurrent.futures import ThreadPoolExecutor

app = Flask(__name__)
cache = Cache(app, config={'CACHE_TYPE': 'SimpleCache'})

@cache.memoize(timeout=3600)
def fetch_and_calculate(config):
    engine = DataEngine(config['symbol'], config['url'], config['provider'])
    df = engine.fetch_data()
    if df is not None:
        metrics = engine.calculate_table_metrics(df)
        if metrics:
            metrics['symbol'] = config['symbol']
            return metrics
    return None

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api/summary')
def get_summary():
    engine_base = DataEngine() 
    instruments = engine_base.load_instruments_from_csv('instruments.csv')
    
    results = []
    for item in instruments:
        engine = DataEngine(
            symbol=item['symbol'], 
            url=item['url'], 
            provider=item['provider']
        )
        
        metrics = engine.get_local_metrics()
        
        if metrics and isinstance(metrics, dict):
            metrics['symbol'] = item['symbol']
            results.append(metrics)
        else:
            # 🔥 FIX: Include the 'error' key so JavaScript hits the Gatekeeper
            results.append({
                "symbol": item['symbol'], 
                "last_close": None, # Ensure this is null, not the string "No Data"
                "error": True 
            })
            
    return jsonify(results)

@app.route('/api/sync', methods=['POST'])
def run_sync():
    # ✅ THIS RUNS THE FULL fetch_data() WITH NETWORK ACCESS
    engine = DataEngine()
    report = engine.global_sync()
    return jsonify(report)

@app.route('/api/backtest', methods=['POST'])
def api_backtest():
    data = request.get_json() or {}
    
    # 1. Extract and Sanitize Symbol
    symbol = data.get('symbol', '').strip().upper()
    print(f"DEBUG: Processing {symbol} with payload: {data}")

    if not symbol:
        return jsonify({"error": "Symbol is required"}), 400

    try:
        # 2. Extract and Cast Inputs (Ensuring types match engine requirements)
        # Note: JS uses 'startDate' (camelCase), Python often uses 'start_date'
        initial = float(data.get('initial_inv', 0))
        monthly = float(data.get('monthly_target', 0))
        start_date = data.get('startDate') or data.get('start_date', '2024-01-01')
        frequency = data.get('frequency', 'Monthly')
        
        # Robust Boolean Check
        allow_sell = data.get('allow_sell') is True
        allow_frac = data.get('allow_fractional') is True

        # 3. Initialize Engines
        data_eng = DataEngine(symbol=symbol)
        
        # Verify file exists after DataEngine logic
        if not os.path.exists(data_eng.file_path):
            return jsonify({"error": f"Data for {symbol} could not be retrieved."}), 404
            
        strat_eng = StrategyEngine(data_eng)
        
        # 4. Calculation - Calling the correctly named method 'run_simulation'
        # Ensure arguments match the signature in your engine.py
        history = strat_eng.run_simulation(
            start_date=start_date,
            monthly_goal=monthly,
            initial_inv=initial,
            frequency=frequency,
            allow_sell=allow_sell,
            allow_fractional=allow_frac
        )

        return jsonify(history)

    except Exception as e:
        import traceback
        print("CRITICAL ERROR in /api/backtest:")
        print(traceback.format_exc()) 
        # Returning the actual error message helps debugging the '500' faster
        return jsonify({"error": str(e)}), 500

@app.route('/backtest') # This is the URL you will actually visit
def backtest_ui():
    # This sends the HTML file to your browser
    return render_template('val_avg_cal.html')

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)