import os
import shutil
import sys
from thefirstock import thefirstock 
from datetime import datetime
import pytz
import uuid
import pprint


class ClientFileProcessor:
    def __init__(self, base_folder, client_details, client_code):
        self.base_folder = base_folder
        self.client_details = client_details
        self.client_id = client_details[0]
        self.client_folder = os.path.join(base_folder, self.client_id)

        # Create the client folder if it doesn't exist
        os.makedirs(self.client_folder, exist_ok=True)
        os.chdir(self.client_folder)
        self.loginDone = False
        self.trackOrderId = 0

        default_symbol_properties = {
                "NIFTY":      {"quantity": 75, "expiry": "06FEB25", "exchange": "NFO", "enabled": False, "margin": 10, 'multiplier': 1},
                "BANKNIFTY":  {"quantity": 30,  "expiry": "27FEB25", "exchange": "NFO", "enabled": False, "margin": 25, 'multiplier': 1},
                "MIDCPNIFTY": {"quantity": 120,  "expiry": "27FEB25", "exchange": "NFO", "enabled": False, "margin": 10, 'multiplier': 1},
                "FINNIFTY":   {"quantity": 65,  "expiry": "27FEB25", "exchange": "NFO", "enabled": False, "margin": 10, 'multiplier': 1},
                "SENSEX":     {"quantity": 20,  "expiry": "25204",   "exchange": "BFO", "enabled": False, "margin": 25, 'multiplier': 1},
            }


        if client_code == 'TT':
            self.symbol_properties = default_symbol_properties.copy()
            self.symbol_properties["NIFTY"]["enabled"] = True
            self.symbol_properties["NIFTY"]["margin"] = 25
            self.symbol_properties["NIFTY"]["multiplier"] = 3


        elif client_code == 'RA':
            self.symbol_properties = default_symbol_properties.copy()
            self.symbol_properties["SENSEX"]["enabled"] = True
            self.symbol_properties["SENSEX"]["margin"] = 50
            #self.symbol_properties["SENSEX"]["multiplier"] = 3


        elif client_code == 'DB':
            self.symbol_properties = default_symbol_properties.copy()
            #self.symbol_properties["SENSEX"]["enabled"] = True
            self.symbol_properties["SENSEX"]["margin"] = 30
            self.symbol_properties["SENSEX"]["multiplier"] = 2
            
        else:
            raise ValueError(f"Unknown client code: {client_code}")



    def getProfitMargin(self, tradingSymbol):

        if tradingSymbol.upper().startswith('NIFTY'):
            key = 'NIFTY'
        elif tradingSymbol.upper().startswith('BANKNIFTY'):
            key = 'BANKNIFTY'
        elif tradingSymbol.upper().startswith('MIDCPNIFTY'):
            key = 'MIDCPNIFTY'
        elif tradingSymbol.upper().startswith('FINNIFTY'):
            key = 'FINNIFTY'
        elif tradingSymbol.upper().startswith('SENSEX'):
            key = 'SENSEX'
        else:
            key = 'NIFTY'
        
        margin = self.symbol_properties[key]['margin']
        #print(f"getProfitMargin key={key}  margin={margin}")
        return margin
        

    def login(self, client):

        print(client)
        self.userId = client[0]
        password = client[1]
        TOTP = client[2]
        vendorCode = client[3]
        apiKey = client[4]

        print("Attempting to login")
        login_response = thefirstock.firstock_login(
            userId=self.userId,
            password=password,
            TOTP=TOTP,
            vendorCode=vendorCode,
            apiKey=apiKey
        )
        if login_response['status'] == 'success':
            print("Login successful")
        else:
            print("Login failed: %s", login_response)


    def CheckAndManipulateQuantity(self, base_symbol, orderType, expiry, quantity, multiplier):

        try:

            if base_symbol == "SENSEX":
                if orderType == 'CE':
                    search_str = 'PE'
                elif orderType == 'PE':
                    search_str = 'CE'
            else:
                if orderType == 'C':
                    search_str = 'P'
                elif orderType == 'P':
                    search_str = 'C'


            orderBook = thefirstock.firstock_orderBook( self.client_id )
            orders = orderBook['data']

            myOrders = []
            for order in orders:
                remarks = str(order.get('remarks', ''))  # Safely get 'remarks' and convert to string
                if remarks.lower().startswith('test'):  # Case-insensitive check
                    myOrders.append(order)

            sellOrderCounterOrderDict={}
            sellOrderSameOrderDict={}

            for order in myOrders:
                key = order.get('remarks', '')
                type = order.get('transactionType', '')
                status = order.get('status', '')
                tradingSymbol = order.get('tradingSymbol', '')

                if type == 'S' :
                    if status != 'COMPLETE' and status != 'CANCELED' and status != 'REJECTED':
                        if tradingSymbol.startswith(base_symbol):
                            symbol = tradingSymbol.replace(base_symbol, '')
                            symbol = symbol.replace(expiry, '')
                            new_symbol = symbol.replace(search_str, '')
                            if symbol != new_symbol:
                                sellOrderCounterOrderDict[key] = order
                            else:
                                sellOrderSameOrderDict[key] = order


            if len(sellOrderCounterOrderDict) != 0 and len(sellOrderSameOrderDict) == 0:
                quantity = quantity * multiplier
                print(f'Direction Change Detected with an outstanding order. New Quantity = {quantity}')

        except:
            pass

        return str(quantity)


    
    def process_file(self, file_path):
        symbol = file_path.split('__')[1]
        price = '0.0'

        # Mapping for symbol properties
        symbol_properties = self.symbol_properties

        # Determine the base symbol
        base_symbol = next((key for key in symbol_properties if symbol.startswith(key)), None)
        if not base_symbol:
            raise ValueError(f"Unrecognized symbol: {symbol}")

        # Get properties for the symbol
        properties = symbol_properties[base_symbol]
        quantity = properties["quantity"]
        expiry = properties["expiry"]
        exchange = properties["exchange"]
        tradeEnabled = properties["enabled"]
        multiplier = int(properties["multiplier"])

        # Extract instrument details
        instrument_pre = symbol.replace(base_symbol, "")
        instrument = instrument_pre.replace("PE", "").replace("CE", "")
        instrument_post = "C" if "CE" in instrument_pre else "P" if "PE" in instrument_pre else None

        # Construct trading symbol
        if base_symbol == "SENSEX":
            trading_symbol = f"{base_symbol}{expiry}{instrument_pre}"
            new_order_type = instrument_pre[-2:]
        else:
            trading_symbol = f"{base_symbol}{expiry}{instrument_post}{instrument}"
            new_order_type = instrument_post


        remarks = 'test_' + str(uuid.uuid4().int & 0xFFFFFFFF)


        if tradeEnabled:

            if multiplier > 0:
                print(f'multiplier Enabled{multiplier} . Checking Quanity modification ...')
                quantity = self.CheckAndManipulateQuantity(base_symbol, new_order_type, expiry, int(quantity), multiplier)

            # Print and log order details
            print(
                f"Placing order with params: userId={self.userId}, exchange={exchange}, "
                f"tradingSymbol={trading_symbol}, quantity={quantity}, price={price}, "
                f"product=M, transactionType=B, priceType=MKT, retention=DAY, triggerPrice=0, remarks={remarks}"
            )

            placeOrder = thefirstock.firstock_placeOrder(
                userId=self.userId,
                exchange=exchange,
                tradingSymbol=trading_symbol,
                quantity=str(quantity),
                price=price,
                product="M",
                transactionType="B",
                priceType="MKT",
                retention="DAY",
                triggerPrice="0",
                remarks=remarks
            )

            print(f"Order response: \n{placeOrder}")

            self.trackOrderId = self.trackOrderId + 1
        else:
            pass
            #print(f"Order disabled for : {base_symbol}")


        return True  # Simulate a successful operation


    def replicate_file(self, file_name):
        """
        Replicate the processed file to the client folder.
        """
        source_path = os.path.join(self.base_folder, file_name)
        target_path = os.path.join(self.client_folder, file_name)

        shutil.copy2(source_path, target_path)
        #print(f"File {file_name} replicated to {self.client_folder}.")

    def process_files(self):
        """
        Process each file in the base folder in creation order.
        Skip directories and already processed files.
        """
        for file_name in sorted(os.listdir(self.base_folder)):
            source_path = os.path.join(self.base_folder, file_name)
            target_path = os.path.join(self.client_folder, file_name)

            # Skip directories and already processed files
            if os.path.isdir(source_path) or os.path.exists(target_path):
                continue

            if not self.loginDone:
                self.login(self.client_details)
                self.loginDone = True

            # Perform the action and replicate if successful
            if self.process_file(source_path):
                self.replicate_file(file_name)
            else:
                print(f"Failed to process file: {file_name}")

    

    def addClosingOrders(self):

        try:

            orderBook = thefirstock.firstock_orderBook( self.client_id )
            orders = orderBook['data']

            myOrders = []
            for order in orders:
                remarks = str(order.get('remarks', ''))  # Safely get 'remarks' and convert to string
                if remarks.lower().startswith('test'):  # Case-insensitive check
                    myOrders.append(order)


            buyCompletedOrderDict={}
            sellOrderDict={}

            for order in myOrders:
                key = order.get('remarks', '')
                type = order.get('transactionType', '')
                status = order.get('status', '')

                if type == 'B' and status == 'COMPLETE':
                    buyCompletedOrderDict[key] = order

                if type == 'S':
                    sellOrderDict[key] = order


            #sellOrderDict={}

            #print(buyCompletedOrderDict)
            #print(sellOrderDict)


            for key in buyCompletedOrderDict:
                if key not in sellOrderDict:
                    
                    orderDetails = buyCompletedOrderDict[key]
                    userId = orderDetails['userId']
                    exchange = orderDetails['exchange']
                    tradingSymbol = orderDetails['tradingSymbol']
                    quantity = orderDetails['quantity']
                    price = float(orderDetails['averagePrice'])
                    price = price  +  self.getProfitMargin(tradingSymbol)
                    price = float (int (price * 10 ) / 10 )
                    product = orderDetails['product']
                    transactionType = 'S'
                    priceType = 'LMT'
                    retention = orderDetails['retention']


                    # Print and log order details
                    print(
                        f"Placing Sell order with params: userId={userId}, exchange={exchange}, "
                        f"tradingSymbol={tradingSymbol}, quantity={quantity}, price={price}, "
                        f"product={product}, transactionType={transactionType}, priceType={priceType}, "
                        f"retention={retention}, triggerPrice=0, remarks={key}"
                    )

                    placeOrder = thefirstock.firstock_placeOrder(
                        userId=userId,
                        exchange=exchange,
                        tradingSymbol=tradingSymbol,
                        quantity=str(quantity),
                        price=str(price),
                        product=product,
                        transactionType=transactionType,
                        priceType=priceType,
                        retention=retention,
                        triggerPrice="0",
                        remarks=key
                    )

                    print(f"Sell Order response: \n{placeOrder}")

        
        except Exception as e:
            print("An unexpected error occurred:", str(e))

        
        


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python script_name.py <client_code>")
        sys.exit(1)
    
    client_code = sys.argv[1]
    client_details = {
        'TT': ['TT1582', 'O9i8u7y6$$', '15111982', 'TT1582_API', '8d54070744a45d26b327e1afc7e02a9e'],
        'RA': ['RA1383', 'O9i8u7y6$$', '13061983', 'RA1383_API', '45e24dbc98a875e94faf8a7479165ed8'],
        'DB': ['DB1485', '$L10n-one', '14121985', 'DB1485_API', '7d859ddc9afeedc2a712a092051b2814']
    }

    if client_code not in client_details:
        print(f"Error: Client code '{client_code}' not found.")
        sys.exit(1)
    
    client_data = client_details[client_code]
    ist = pytz.timezone('Asia/Kolkata')
    current_time = datetime.now(ist).strftime('%Y-%m-%d %H:%M:%S')
    print(f"\n[{current_time}] Processing for client: {client_data[0]}")

    base_folder = "/var/www/html/ACTIONS/"

    processor = ClientFileProcessor(base_folder, client_data, client_code)
    processor.process_files()


    processor.addClosingOrders()


