from datetime import datetime, timedelta
import ujson
import asyncio
import aiohttp
import os
from dotenv import load_dotenv
import sqlite3
import pandas as pd
from tqdm import tqdm

# Load environment variables
load_dotenv()
api_key = os.getenv('FMP_API_KEY')


query_template = """
    SELECT date, close
    FROM "{ticker}"
    WHERE date BETWEEN ? AND ?
"""

# Function to save JSON data
async def save_json(symbol, data):
    with open(f'json/fomc-impact/companies/{symbol}.json', 'w') as file:
        ujson.dump(data, file)

# Function to fetch data from the API
async def get_data(session, url):
    async with session.get(url) as response:
        data = await response.json()
        return data

async def get_fomc_data():
    fomc_data = []
    start_date = datetime.now() - timedelta(days=365)
    end_date = datetime.now()
    
    async with aiohttp.ClientSession() as session:
        current_date = start_date
        while current_date < end_date:
            next_date = min(current_date + timedelta(days=10), end_date)
            start_str = current_date.strftime('%Y-%m-%d')
            end_str = next_date.strftime('%Y-%m-%d')
            
            url = f"https://financialmodelingprep.com/api/v3/economic_calendar?from={start_str}&to={end_str}&apikey={api_key}"
            data = await get_data(session, url)
            if data:
                # Filter for "FOMC Economic Projections" events
                fomc_events = [item for item in data if item.get('event') == "Fed Interest Rate Decision"]
                fomc_data.extend(fomc_events)
            
            # Move to the next 10-day period
            current_date = next_date

    filtered_data = [
    {
        'date': item['date'][0:10],
        'changePercentage': item['changePercentage'],
        'previous': item['previous'],
        'actual': item['actual'],
        'estimate': item['estimate']
    }
        for item in fomc_data
    ]

    filtered_data = sorted(filtered_data, key=lambda x: x['date'])

    return filtered_data


async def run():
    fomc_dates = await get_fomc_data()  # Assumed to return the list of dictionaries as provided
    start_date = datetime.now() - timedelta(days=365)
    end_date = datetime.now()
    # Extracting the dates for filtering
    fomc_dates_list = [datetime.strptime(fomc['date'], '%Y-%m-%d').date() for fomc in fomc_dates]
    # Connect to SQLite databases
    stock_con = sqlite3.connect('stocks.db')
    etf_con = sqlite3.connect('etf.db')
    stock_cursor = stock_con.cursor()
    stock_cursor.execute("PRAGMA journal_mode = wal")
    stock_cursor.execute("SELECT DISTINCT symbol FROM stocks WHERE symbol NOT LIKE '%.%' AND marketCap >= 500E6")
    stock_symbols = [row[0] for row in stock_cursor.fetchall()]
    etf_cursor = etf_con.cursor()
    etf_cursor.execute("PRAGMA journal_mode = wal")
    etf_cursor.execute("SELECT DISTINCT symbol FROM etfs")
    etf_symbols = [row[0] for row in etf_cursor.fetchall()]

    total_symbols = stock_symbols + etf_symbols
    
    for ticker in tqdm(total_symbols):
        try:
            query = query_template.format(ticker=ticker)
            connection = stock_con if ticker in stock_symbols else etf_con
            df_price = pd.read_sql_query(query, connection, params=(start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d')))

            if len(df_price) > 150 and len(fomc_dates) > 0:
                # Convert 'date' column in df_price to datetime.date for comparison
                df_price['date'] = pd.to_datetime(df_price['date']).dt.date
                # Filter out every fifth row, unless the date is in fomc_dates
                filtered_df = df_price[
                    (df_price.index % 5 != 0) | (df_price['date'].isin(fomc_dates_list))
                ]
                filtered_df['date'] = filtered_df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))
                # Prepare the result with filtered data and original fomc_dates
                fomc_data_unique = {}
                for fomc in fomc_dates:
                    date = fomc['date']
                    if date not in fomc_data_unique:  # Check for duplicates
                        fomc_data_unique[date] = {
                            'date': date,
                            'changePercentage': fomc['changePercentage'],
                            'previous': fomc['previous'],
                            'actual': fomc['actual'],
                            'estimate': fomc['estimate']
                        }
                # Convert the unique FOMC data back to a list
                res = {
                    'fomcData': list(fomc_data_unique.values()),  # Ensure unique dates
                    'history': filtered_df.to_dict('records')
                }
                # Compute percentage changes for FOMC dates
                for i in range(len(res['fomcData'])):
                    current_fomc_date = res['fomcData'][i]['date']
                    current_price_row = filtered_df[filtered_df['date'] == current_fomc_date]
                    if i == len(res['fomcData']) - 1:
                        # This is the last FOMC date, so compare it to the last price in the dataframe
                        last_price_row = filtered_df.iloc[-1]
                        current_price = current_price_row['close'].values[0]
                        next_price = last_price_row['close']
                    else:
                        next_fomc_date = res['fomcData'][i + 1]['date']
                        next_price_row = filtered_df[filtered_df['date'] == next_fomc_date]
                        if not current_price_row.empty and not next_price_row.empty:
                            current_price = current_price_row['close'].values[0]
                            next_price = next_price_row['close'].values[0]
                    # Calculate the percentage change
                    percentage_change = ((next_price - current_price) / current_price) * 100
                    res['fomcData'][i]['changePercentage'] = round(percentage_change, 2)  # Update with the new change percentage
                await save_json(ticker, res)
        except Exception as e:
            print(f"Error processing {ticker}: {e}")
# Run the asyncio event loop
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
