import numpy as np

import csv

def read_crypto_csv(filename):
    """
    Converts a CSV file of cryptocurrency prices into a dictionary format.
    
    Args:
        filename (str): Path to the CSV file
        
    Returns:
        dict: {coin_symbol: list_of_prices}
    """
    crypto_data = {}
    
    with open(filename, 'r') as f:
        reader = csv.reader(f)
        headers = next(reader)  # Read header row
        
        # Verify CSV format (first column should be 'Symbol')
        if headers[0] != 'Symbol':
            raise ValueError("CSV format incorrect. First column should be 'Symbol'")
            
        # Process each row
        for row in reader:
            symbol = row[0]
            prices = [float(price) for price in row[1:]]  # Convert prices to floats
            
            crypto_data[symbol] = prices
            
    return crypto_data



def detect_trend(data, window_size=10, slope_threshold=0.1):
    """
    Detects upward/downward trends for multiple coins using moving average slopes.
    
    Args:
        data (dict): Dictionary of {coin: list_of_prices}
        window_size (int): Days to analyze for initial trend
        slope_threshold (float): Slope magnitude threshold for trend classification
    
    Returns:
        dict: {coin: {'trend': 'upward'/'downward'/'flat', 'slope': float}}
    """
    results = {}
    
    for coin, prices in data.items():
        if len(prices) < window_size:
            raise ValueError(f"Not enough data for {coin}. Needs at least {window_size} days")
            
        # Calculate moving average
        window_prices = prices[:window_size]
        x = np.arange(window_size)
        y = np.array(window_prices)
        
        # Calculate slope using linear regression
        numerator = window_size * np.sum(x*y) - np.sum(x) * np.sum(y)
        denominator = window_size * np.sum(x**2) - (np.sum(x))**2
        slope = numerator / denominator if denominator != 0 else 0
        
        # Classify trend
        if slope > slope_threshold:
            trend = 'upward'
        elif slope < -slope_threshold:
            trend = 'downward'
        else:
            trend = 'flat'
            
        results[coin] = {'trend': trend, 'slope': slope}
        
    return results

def validate_trend(data, initial_trends, window_size=10, validation_period=5, slope_threshold=0.1):
    """
    Validates trends by analyzing subsequent price movements.
    
    Args:
        data (dict): Dictionary of {coin: list_of_prices}
        initial_trends (dict): Results from detect_trend()
        window_size (int): Initial detection window size
        validation_period (int): Days after window_size to analyze
        slope_threshold (float): Slope threshold for validation
    
    Returns:
        dict: {coin: {'initial_trend': str, 'validation_trend': str, 'result': str}}
    """
    validation_results = {}
    
    for coin, prices in data.items():
        if len(prices) < window_size + validation_period:
            raise ValueError(f"Not enough data for validation for {coin}")
            
        # Get validation window prices (days 11-16 for window_size=10, validation_period=5)
        validation_prices = prices[window_size:window_size+validation_period]
        
        # Calculate validation trend
        x_val = np.arange(validation_period)
        y_val = np.array(validation_prices)
        
        numerator_val = validation_period * np.sum(x_val*y_val) - np.sum(x_val) * np.sum(y_val)
        denominator_val = validation_period * np.sum(x_val**2) - (np.sum(x_val))**2
        slope_val = numerator_val / denominator_val if denominator_val != 0 else 0
        
        # Classify validation trend
        if slope_val > slope_threshold:
            val_trend = 'upward'
        elif slope_val < -slope_threshold:
            val_trend = 'downward'
        else:
            val_trend = 'flat'
            
        # Determine validation result
        initial = initial_trends[coin]['trend']
        
        if initial == 'flat':
            if val_trend != 'flat':
                result = f'New {val_trend} trend emerged'
            else:
                result = 'Continued flat'
        else:
            if val_trend == initial:
                result = 'Trend continued'
            elif val_trend == 'flat':
                result = 'Trend weakened to flat'
            else:
                result = 'Trend reversed'
                
        validation_results[coin] = {
            'initial_trend': initial,
            'validation_trend': val_trend,
            'result': result,
            'validation_slope': slope_val
        }
        
    return validation_results

# Usage example
if __name__ == '__main__':
    # Convert CSV to crypto_data structure
    crypto_data = read_crypto_csv('crypto_prices.csv')

    # Detect initial trends
    initial_results = detect_trend(crypto_data, window_size=10)

    # Validate trends using next 5 days
    validation_results = validate_trend(crypto_data, initial_results, window_size=10, validation_period=5)

    # Print formatted results
    print("Coin\t\tInitial\t\tValidation\tResult")
    print("-----------------------------------------------------------")
    for coin, result in validation_results.items():
        print(f"{coin}\t{result['initial_trend']:8}\t{result['validation_trend']:8}\t{result['result']}")

    # # Example: Print first 3 coins and their first 5 prices
    # for i, (coin, prices) in enumerate(crypto_data.items()):
    #     if i >= 3:
    #         break
    #     print(f"{coin}: {prices[:5]}...")
