import json
import datetime
import requests
import pandas as pd
from datetime import date
from pymongo import MongoClient
from io import StringIO

client = MongoClient("mongodb://jenya:DJenya$Mongo%40St0ckDB@172.105.59.175:27017/")
db = client["trade_iq"]
credsColl = db["zerodha_credentials"]

creds = credsColl.find_one({"date": str(date.today())})
enctoken = creds.get("enctoken")

def fetch_tokens():
    """
    Fetches instrument tokens from Zerodha API.
    Returns the API response.
    """
    try:
        creds = credsColl.find_one({"date": str(date.today())})
        if not creds:
            raise Exception("No credentials found for today")

        enctoken = creds.get("enctoken")
        if not enctoken:
            raise Exception("Enctoken not found in credentials")

        url = "https://api.kite.trade/instruments"
        headers = {
            'X-Kite-Version': '3',
            'Authorization': f'enctoken {enctoken}'
        }

        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise exception for non-200 status codes
        return response

    except Exception as e:
        print(f"Error fetching tokens: {str(e)}")
        return None

def dataframe_data():
    """
    Processes the instruments data and converts it to a DataFrame.
    """
    try:
        response = fetch_tokens()
        if response is None:
            return None

        # Convert CSV string to DataFrame using StringIO
        df = pd.read_csv(StringIO(response.text))

        # Basic data validation
        if df.empty:
            print("No data received from API")
            return None

        return df

    except Exception as e:
        print(f"Error processing data: {str(e)}")
        return None

def process_data():
    df = dataframe_data()
    filtered_df = df[df["exchange"] == "NSE"]

    today = datetime.datetime.today().strftime("%Y-%m-%d")
    today = datetime.datetime.strptime(today, "%Y-%m-%d")
    yesterday = (today - datetime.timedelta(days=1)).date()
    default_start_date = datetime.date(2014, 1, 1)

    # Get enctoken from Credentials Collection
    enctoken = creds.get("enctoken")
    if not enctoken:
        raise Exception("Enctoken not found in credentials")

    # Set up headers for API request
    headers = {
        'accept': '*/*',
        'accept-language': 'en-US,en;q=0.9',
        'authorization': f'enctoken {enctoken}'
    }

    for i in filtered_df.itertuples():
        index, instrument_token, exchange_token, tradingsymbol, name, last_price, expiry, strike, tick_size, lot_size, instrument_type, segment, exchange = i
        collection = db["nse_data1"]

        existing_document = collection.find_one({'symbol': tradingsymbol})
        if existing_document:
            # If exists, find the last recorded date
            try:
                last_date = max(datetime.datetime.strptime(date, '%Y-%m-%d').date() for date in existing_document['prices'].keys())
                from_date = last_date + datetime.timedelta(days=1)
            except ValueError:
                from_date = default_start_date

            if from_date > yesterday:
                print(f"Data for {tradingsymbol} is up to date.")
                continue
        else:
            # If not exists, set from_date to the default start date
            from_date = default_start_date

        print(f"Processing {tradingsymbol} from {from_date} to {yesterday}")

        # Filter rows
        filtered_df = df.loc[
            (df["tradingsymbol"] == tradingsymbol) &
            (df["exchange"] == "NSE"),
            ["instrument_token", "segment", "exchange_token", "name"]
        ]

        for j in filtered_df.itertuples():
            index, inner_instreument_token, inner_segment, inner_exchange_token, inner_name = j

            if inner_instreument_token is not None:
                url = f"https://kite.zerodha.com/oms/instruments/historical/{inner_instreument_token}/day?user_id=GMG829&oi=0&from={from_date}&to={yesterday}"
                response = json.loads(requests.request("GET", url, headers=headers, data={}).text)

                try:
                    if response and 'data' in response and 'candles' in response['data']:
                        new_prices = {}
                        for candle in response['data']['candles']:
                            candle_date = datetime.datetime.strptime(candle[0].split('T')[0], '%Y-%m-%d').date()
                            ohlc = {
                                'open': candle[1],
                                'high': candle[2],
                                'low': candle[3],
                                'close': candle[4]
                            }
                            new_prices[candle_date.strftime('%Y-%m-%d')] = ohlc

                        if existing_document:
                            # Update existing document
                            existing_document['prices'].update(new_prices)
                            existing_document['timestamp'] = datetime.datetime.now()
                            collection.replace_one({'symbol': tradingsymbol}, existing_document)
                        else:
                            # Insert new document
                            new_document = {
                                'symbol': tradingsymbol,
                                'company_name': name,
                                'Instrument': segment,
                                'exchange_token': int(exchange_token),
                                'instrument_token': int(inner_instreument_token),
                                'timestamp': datetime.datetime.now(),
                                'prices': new_prices
                            }
                            # collection.insert_one(new_document)

                            print(new_document)

                        print(f"Completed processing {tradingsymbol}")
                    else:
                        print(f"No new data available for {tradingsymbol}.")
                except Exception as e:
                    print(f"Error processing {tradingsymbol}: {e}")
        else:
            print(f"No instrument token found for {tradingsymbol}")

    print("Processing completed. Results saved to MongoDB")
    client.close()

if __name__ == "__main__":
    df = process_data()
    if df is not None:
        print(df.head())  # Print first 5 rows instead of entire DataFrame
        print(f"Total instruments: {len(df)}")