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
import pandas as pd


app = Flask(__name__)
cache = Cache(app, config={'CACHE_TYPE': 'SimpleCache'})
# The CSV is in the root directory (same level as app.py)
CSV_PATH = os.path.join(os.path.dirname(__file__), 'instruments.csv')

@app.route('/settings')
def settings():
    instruments = []
    last_updated = "Never"
    
    if os.path.exists(CSV_PATH):
        # 1. Get the last modified time from the Synology filesystem
        mtime = os.path.getmtime(CSV_PATH)
        last_updated = datetime.fromtimestamp(mtime).strftime('%Y-%m-%d %H:%M:%S')
        
        # 2. Read the data
        df = pd.read_csv(CSV_PATH)
        df = df.fillna('')
        instruments = df.to_dict(orient='records')
    
    return render_template('settings.html', instruments=instruments, last_updated=last_updated)

@app.route('/settings/save', methods=['POST'])
def save_settings():
    try:
        names = request.form.getlist('name[]')
        cusips = request.form.getlist('cusip[]')
        providers = request.form.getlist('provider[]')
        
        # Create a new DataFrame from the web form data
        new_data = {
            'name': [s.strip() for s in names if s.strip()],
            'cusip': [u.strip() for u in cusips if u.strip()],
            'provider': [p.strip() for p in providers if p.strip()]
        }
        
        df = pd.DataFrame(new_data)
        # Save directly back to the root folder
        df.to_csv(CSV_PATH, index=False)
        
        return redirect('/settings')
    except Exception as e:
        print(f"Error saving CSV: {e}")
        return "Internal Server Error", 500

@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 {}
    symbol = data.get('symbol', '').strip().upper()
    engine = DataEngine(symbol=symbol)
    
    if not symbol:
        return jsonify({"error": "Symbol is required"}), 400

    try:
        # 1. Initialize the Engine 
        # (The Engine's __init__ should handle looking up the URL in instruments.csv)
        data_eng = DataEngine(symbol=symbol)
        
        # 2. Trigger Smart Fetch 
        # (Inside engine.py, this checks the 24h clock and updates if needed)
        data_eng.fetch_data() 
        
        # 3. Verify data exists before proceeding
        if not os.path.exists(data_eng.file_path):
            return jsonify({"error": f"No data found for {symbol}"}), 404
            
        # 4. Run Strategy
        strat_eng = StrategyEngine(data_eng)
        history = strat_eng.run_simulation(
            start_date=data.get('startDate', '2024-01-01'),
            monthly_goal=float(data.get('monthly_target', 0)),
            initial_inv=float(data.get('initial_inv', 0)),
            frequency=data.get('frequency', 'Monthly'),
            allow_sell=data.get('allow_sell') is True,
            allow_fractional=data.get('allow_fractional') is True
        )

        return jsonify(history)

    except Exception as e:
        app.logger.error(f"Backtest Error: {str(e)}")
        return jsonify({"error": "Internal server error"}), 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)