from flask import Flask, render_template, jsonify
from engine import DataEngine
import concurrent.futures
from flask_caching import Cache
import csv
import os
import logging

app = Flask(__name__)

# Configure caching
cache = Cache(app, config={'CACHE_TYPE': 'SimpleCache'})

# Configure logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

# Function to load instruments from a CSV file
def load_instruments_from_csv(file_path):
    instruments = []
    try:
        abs_path = os.path.join(os.path.dirname(__file__), file_path)
        # 'utf-8-sig' handles the hidden characters Excel often adds
        with open(abs_path, mode='r', encoding='utf-8-sig') as csvfile:
            # Clean spaces from column names automatically
            reader = csv.DictReader(csvfile)
            reader.fieldnames = [name.strip().lower() for name in reader.fieldnames]
            
            for row in reader:
                symbol = row.get('symbol', '').strip()
                cusip = row.get('cusip', '').strip()
                
                if symbol and cusip:
                    url = f"https://am.jpmorgan.com/FundsMarketingHandler/historicalData?cusip={cusip}&country=hk&role=per&userLoggedIn=false&language=en&version=6.9.0_1684"
                    instruments.append({"symbol": symbol, "url": url})
        
        logging.info(f"Successfully loaded {len(instruments)} instruments.")
    except Exception as e:
        logging.error(f"Error reading CSV file: {e}")
    return instruments

# Load instruments from CSV
URL_CONFIG = load_instruments_from_csv('instruments.csv')

# Log the contents of URL_CONFIG to verify instruments are loaded
logging.debug(f"Loaded instruments: {URL_CONFIG}")

@cache.memoize(timeout=86400)  # Cache results for 24 hours
def fetch_and_calculate(config):
    try:
        logging.debug(f"Fetching data for: {config['symbol']}")
        engine = DataEngine(config['url'])
        df = engine.fetch_data()
        if df is None or df.empty:
            logging.warning(f"No data fetched for: {config['symbol']}")
            return None
        
        metrics = engine.calculate_table_metrics(df)
        if metrics:
            metrics['symbol'] = config['symbol']
            logging.debug(f"Metrics calculated for {config['symbol']}: {metrics}")
            return metrics
        logging.warning(f"Metrics calculation failed for: {config['symbol']}")
        return None
    except Exception as e:
        logging.error(f"Error processing {config['symbol']}: {e}")
        return None

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

@app.route('/api/summary')
def get_summary():
    results = []
    # Use ThreadPoolExecutor for faster parallel fetching
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        future_to_config = {executor.submit(fetch_and_calculate, cfg): cfg for cfg in URL_CONFIG}
        for future in concurrent.futures.as_completed(future_to_config):
            res = future.result()
            if res:
                results.append(res)
    
    # Sort by symbol name
    results.sort(key=lambda x: x['symbol'])
    return jsonify(results)

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