import json
import sys
import base64
import time
import math
from kiteconnect import KiteConnect
import requests


from __config import CONFIG
from __mySqlConnector import MYSQLCONNECTOR


hideDisplayingPrice = False


ohlcRow = '''
    <div class="row mt-4 mb-4 justify-content-center">
        <div class="col-md-2 mt-2 border border-dark border-thick">
            <div class="row justify-content-center border-bottom border-dark">
                <div class="col text-center border-info bg-info text-white"><strong>Price</strong></div>
            </div>
            <div class="row justify-content-center border-bottom border-dark">
                <div class="col text-center border-info bg-info text-white"><strong>__currentPrice__</strong></div>
            </div>
        </div>
    </div>
    <div class="row justify-content-center">
        <div class="col-md-6 mt-2 border border-dark">
            <div class="row justify-content-center border-bottom border-dark">
                <div class="col text-center border-right border-dark"><strong>Close</strong></div>
                <div class="col text-center border       border-warning border-thick"><strong>Open</strong></div>
                <div class="col text-center border-right border-dark"><strong>High</strong></div>
                <div class="col text-center border-dark"><strong>Low</strong></div>
            </div>
            <div class="row justify-content-center border-bottom border-dark ">
                <div class="col text-center border-right border-dark"><strong>__close__</strong></div>
                <div class="col text-center border       border-warning border-thick"><strong>__open__</strong></div>
                <div class="col text-center border-right border-dark"><strong>__high__</strong></div>
                <div class="col text-center border-dark"><strong>__low__</strong></div>
            </div>
        </div>
    </div>
    '''

row1 = '''
    <div class="row border border-dark mt-4 ">
        <div class="col-2 border-right border-dark"> <!-- Empty cell for spacing --></div>
        <div class="col-2 border-bottom border-right border-dark __bg1__"><strong>__expiry1__</strong></div>
        <div class="col-2 border-bottom border-right border-dark __bg2__"><strong>__expiry2__</strong></div>
        <div class="col-2 border-bottom border-right border-dark __bg3__"><strong>__expiry3__</strong></div>
        <div class="col-2 border-bottom border-right border-dark __bg4__"><strong>__expiry4__</strong></div>
        <div class="col-2 border-bottom border-dark __bg5__"><strong>__expiry5__</strong></div>
    </div>
    '''

rowXHeader = '''
    <div class="row border border-dark">
        <div class="col-2 border-right border-dark"><strong>Strike Price</strong></div>
        <div class="col-1 border-right border-dark"><strong>Call</strong></div>
        <div class="col-1 border-right border-dark"><strong>Put</strong></div>
        <div class="col-1 border-right border-dark"><strong>Call</strong></div>
        <div class="col-1 border-right border-dark"><strong>Put</strong></div>
        <div class="col-1 border-right border-dark"><strong>Call</strong></div>
        <div class="col-1 border-right border-dark"><strong>Put</strong></div>
        <div class="col-1 border-right border-dark"><strong>Call</strong></div>
        <div class="col-1 border-right border-dark"><strong>Put</strong></div>
        <div class="col-1 border-right border-dark"><strong>Call</strong></div>
        <div class="col-1 border-dark"><strong>Put</strong></div>
    </div>
        '''

rowX = '''
    <div class="row border __border_color__">
        <div class="col-2 border-right border-dark border-thick">__StrikePrice__</div>
        <div class="col-1 border-right border-dark __rowCEPEMatch1__ __colorSchemaCE1__ __prevNextCE1__" sym="__expiryCE1__">__expiryPriceCE1__</div>
        <div class="col-1 border-right border-dark border-thick __rowCEPEMatch1__ __colorSchemaPE1__ __prevNextPE1__" sym="__expiryPE1__">__expiryPricePE1__</div>
        <div class="col-1 border-right border-dark __rowCEPEMatch2__ __colorSchemaCE2__ __prevNextCE2__" sym="__expiryCE2__">__expiryPriceCE2__</div>
        <div class="col-1 border-right border-dark border-thick __rowCEPEMatch2__ __colorSchemaPE2__ __prevNextPE2__" sym="__expiryPE2__">__expiryPricePE2__</div>
        <div class="col-1 border-right border-dark __rowCEPEMatch3__ __colorSchemaCE3__ __prevNextCE3__" sym="__expiryCE3__">__expiryPriceCE3__</div>
        <div class="col-1 border-right border-dark border-thick __rowCEPEMatch3__ __colorSchemaPE3__ __prevNextPE3__" sym="__expiryPE3__">__expiryPricePE3__</div>
        <div class="col-1 border-right border-dark __rowCEPEMatch4__ __colorSchemaCE4__ __prevNextCE4__" sym="__expiryCE4__">__expiryPriceCE4__</div>
        <div class="col-1 border-right border-dark border-thick __rowCEPEMatch4__ __colorSchemaPE4__ __prevNextPE4__" sym="__expiryPE4__">__expiryPricePE4__</div>
        <div class="col-1 border-right border-dark __rowCEPEMatch5__ __colorSchemaCE5__ __prevNextCE5__" sym="__expiryCE5__">__expiryPriceCE5__</div>
        <div class="col-1 border-thick __rowCEPEMatch5__ __colorSchemaPE5__ __prevNextPE5__" sym="__expiryPE5__">__expiryPricePE5__</div>
    </div>
        '''

def get_access_token():

    with open(CONFIG.token_file, 'r') as file:
        access_token = file.read()

    return access_token


class GETDATA():

    def __init__(self, category):
        self.kite = KiteConnect(api_key=CONFIG.api_key)
        self.kite.set_access_token( get_access_token() )
        self.myConnector = MYSQLCONNECTOR()
        self.category = category
        self.dateToday = CONFIG.formatted_date
        self.expirySymbolPreList = []
        self.strikePriceList = []

        self.debug = ''

    def setTrigger(self, category, stirkePrice, optionType, identifier ):

        textMsg = 'Buy ' + str(category).upper() + ' ' + str(stirkePrice)+ ' ' + str(optionType) + '.  Triggered By - ' + str(identifier)
        identifier = str(category) + '_' + str(stirkePrice) + '_' + str(optionType) + '_' + str(identifier)
        data = { 'textMsg': textMsg, 'identifier': identifier }
        response = requests.post(CONFIG.mailURL, data=data)
        '''
        response_data = response.json()
        if response_data.get('status') != 'OK':
            print(response.text)
        else:
            print('ALL OK')
        '''



    def getBaseInstrumentName(self):
        instrument = ''
        if self.category == 'nifty':
            instrument='NSE:NIFTY 50'
            self.factor = 50
        elif self.category == 'finNifty':
            instrument='NSE:NIFTY FIN SERVICE'
            self.factor = 50
        elif self.category == 'bankNifty':
            instrument='NSE:NIFTY BANK'
            self.factor = 100
        elif self.category == 'midcpNifty':
            instrument='NSE:NIFTY MID SELECT'
            self.factor = 25
        else:
            raise ValueError("Unknown category")
        return instrument

    def nearest_multiple(self, value):
        factor = self.factor
        rounded_value = math.floor(value / factor) * factor
        if value % factor > factor / 2:
            rounded_value += factor
        #print(value , int(rounded_value), self.factor)
        return int(rounded_value)
    
    def round_decimal_places(self, value):
        decimal_places = value - int(value)
        rounded_decimal = round(decimal_places, 2)
        return rounded_decimal
    
    def getComplement(self):

        retVal = 0.0
        if self.sigDecimalClose == 0.0:
            retVal = 0.0
        else:
            retVal = 1.0 - self.sigDecimalClose
        self.sigDecimalCloseComplement = self.round_decimal_places(retVal)
        
    
    def getCurrentPrice(self):
        instrument = self.getBaseInstrumentName()
        self.quote = self.kite.quote(instrument)[instrument]
        ohlc = self.quote['ohlc']
        self.curPrice = round(float(self.quote['last_price']), 2)
        self.open = round(float(ohlc['open']), 2)
        self.high = round(float(ohlc['high']), 2)
        self.low = round(float(ohlc['low']), 2)
        self.close = round(float(ohlc['close']), 2)

        self.OpenStike = self.nearest_multiple(self.open)
        self.highStike = self.nearest_multiple(self.high)
        self.lowStike = self.nearest_multiple(self.low)
        self.curStike = self.nearest_multiple(self.curPrice)
        self.sigDecimalClose = self.round_decimal_places(self.close)
        self.getComplement()
 

    def getExpiryData(self):
        expiryDetails = self.myConnector.getExpiryDetails(self.category)
        i = 1
        returnData = row1
        for expiry in expiryDetails:
            expiryReplaceStr = '__expiry' + str(i) + '__'
            bgColorReplaceStr = '__bg' + str(i) + '__'
            bgColor = ''
            if expiry[2] == 1:
                bgColor = ' bg-secondary '
            self.expirySymbolPreList.append(expiry[1])
            returnData = returnData.replace(expiryReplaceStr, expiry[0])
            returnData = returnData.replace(bgColorReplaceStr, bgColor)
            i = i + 1
        return returnData
    
    def getStikePriceData(self):
        strikePriceDetails = self.myConnector.getStrikePriceDetails(self.category)
        for strikePrice in strikePriceDetails:
            self.strikePriceList.append(strikePrice[0])

    def getData(self):

        self.getCurrentPrice()
        
        myOhlcRow = ohlcRow.replace('__currentPrice__', str(self.curPrice))
        myOhlcRow = myOhlcRow.replace('__open__', str(self.open))
        myOhlcRow = myOhlcRow.replace('__high__', str(self.high))
        myOhlcRow = myOhlcRow.replace('__low__', str(self.low))
        myOhlcRow = myOhlcRow.replace('__close__', str(self.close))

        
        htmlCode = myOhlcRow + self.getExpiryData() + rowXHeader
        self.getStikePriceData()

        for strikePrice in self.strikePriceList:
            
            curRow = rowX.replace('__StrikePrice__',str(strikePrice))

            border_color = ' border-dark '

            if int(strikePrice) >= self.lowStike and int(strikePrice) <= self.highStike:
                border_color = ' border-dark bg-dark '
            
            if self.OpenStike == int(strikePrice):
                border_color = ' border-warning bg-dark border-thick'

            if self.curStike == int(strikePrice):
                border_color = ' border-dark bg-info text-white border-thick'
                if self.OpenStike == int(strikePrice):
                    border_color = ' border-warning bg-info text-white border-thick'


                

            curRow = curRow.replace('__border_color__',str(border_color))
            
            i=1
            for SymbolPre in self.expirySymbolPreList:
                
                symbolPrefix = SymbolPre + str(strikePrice) 
                callDecimal = ''
                putDecimal = ''
                for symbolSuffix in ['CE', 'PE']:
                    symbol = symbolPrefix + symbolSuffix
                    
                    expiryReplaceStr = '__expiry' + str(symbolSuffix) + str(i)  + '__'
                    expiryPriceReplaceStr = '__expiryPrice' + str(symbolSuffix) + str(i)  + '__'
                    expiryColorSchemaReplaceStr = '__colorSchema' + str(symbolSuffix) + str(i)  + '__'
                    expiryprevNextReplaceStr = '__prevNext' + str(symbolSuffix) + str(i)  + '__'
                    expiryRowCEPEMatchReplaceStr = '__rowCEPEMatch' + str(i)  + '__'


                    prevOtSymbol = symbol.replace(str(strikePrice), str(int(strikePrice) - int(self.factor)))
                    nextOtSymbol = symbol.replace(str(strikePrice), str(int(strikePrice) + int(self.factor)))

                    price = self.myConnector.getOptionPriceDetails(symbol)
                    curPriceDecimal = self.round_decimal_places(float(price))
                    
                    try:
                        prevOtprice = self.myConnector.getOptionPriceDetails(prevOtSymbol)
                        prevOtpriceDecimal = self.round_decimal_places(float(prevOtprice))
                    except:
                        prevOtpriceDecimal = self.round_decimal_places(0.01)

                    try:
                        nextOtprice = self.myConnector.getOptionPriceDetails(nextOtSymbol)
                        nextOtpriceDecimal = self.round_decimal_places(float(nextOtprice))
                    except:
                        nextOtpriceDecimal = self.round_decimal_places(0.01)

                    prevNextValue = " "
                    if curPriceDecimal == self.sigDecimalClose or curPriceDecimal == self.sigDecimalCloseComplement:
                        if prevOtpriceDecimal == curPriceDecimal  or  nextOtpriceDecimal == curPriceDecimal:

                            if ( symbolSuffix == 'CE' and self.low < strikePrice ) or ( symbolSuffix == 'PE' and self.high > strikePrice):

                                prevNextValue = " bg-danger text-white "
                                # Handle trigger for vertical same decimals

                                if symbolSuffix == 'CE' and nextOtpriceDecimal == curPriceDecimal:
                                    midStikePrice = int(strikePrice) - int(self.factor/2)
                                    nextStikePrice = int(strikePrice) + int(self.factor)
                                    if midStikePrice <= self.curPrice and midStikePrice <= self.high and midStikePrice > self.open and midStikePrice > self.low:
                                        self.setTrigger(self.category, nextStikePrice, 'PE', 'VERTICAL_ZONE1_MATCH' )

                                elif symbolSuffix == 'PE' and prevOtpriceDecimal == curPriceDecimal:
                                    midStikePrice = int(strikePrice) + int(self.factor/2)
                                    prevStikePrice = int(strikePrice) - int(self.factor)
                                    if midStikePrice >= self.curPrice and midStikePrice >= self.low and midStikePrice < self.open and midStikePrice < self.high:
                                        self.setTrigger(self.category, prevStikePrice, 'CE', 'VERTICAL_ZONE1_MATCH' )


                    curRow = curRow.replace(expiryprevNextReplaceStr, prevNextValue)

                    if symbolSuffix == 'CE':
                        callDecimal = self.round_decimal_places(float(price))
                    else:
                        putDecimal = self.round_decimal_places(float(price))
                        rowCEPEMatch = ' '
                        if callDecimal == putDecimal and (self.sigDecimalClose == callDecimal or self.sigDecimalCloseComplement == callDecimal):  
                            rowCEPEMatch = ' bg-danger text-white '

                            t1MidStrikePriceLow = int(strikePrice) - int(self.factor/2)        
                            t1MidStrikePriceHigh = int(strikePrice) + int(self.factor/2)       

                            t2MidStrikePricePE = int(strikePrice) - int(self.factor * 1.5)     
                            t2MidStrikePriceCE = int(strikePrice) + int(self.factor * 1.5)     

                            if self.open < strikePrice and self.low < strikePrice :

                                if self.high >= t2MidStrikePricePE and  self.high <= t1MidStrikePriceLow and self.curPrice >= t2MidStrikePricePE and  self.curPrice <= t1MidStrikePriceLow :
                                    self.setTrigger(self.category, strikePrice, 'PE', 'HORIZONTAL_ZONE2_MATCH' )
                                elif self.high >= t1MidStrikePriceLow and  self.high <= t1MidStrikePriceHigh and self.curPrice >= t1MidStrikePriceLow and  self.curPrice <= t1MidStrikePriceHigh :
                                    self.setTrigger(self.category, strikePrice, 'PE', 'HORIZONTAL_ZONE1_MATCH' )

                            elif self.open > strikePrice and self.high > strikePrice:

                                if self.low >= t1MidStrikePriceHigh and  self.low <= t2MidStrikePriceCE and self.curPrice >= t1MidStrikePriceHigh and  self.curPrice <= t2MidStrikePriceCE :
                                    self.setTrigger(self.category, strikePrice, 'CE', 'HORIZONTAL_ZONE2_MATCH' )
                                elif self.low >= t1MidStrikePriceLow and  self.low <= t1MidStrikePriceHigh and self.curPrice >= t1MidStrikePriceLow and  self.curPrice <= t1MidStrikePriceHigh :
                                    self.setTrigger(self.category, strikePrice, 'CE', 'HORIZONTAL_ZONE1_MATCH' )
                            

                        curRow = curRow.replace(expiryRowCEPEMatchReplaceStr, rowCEPEMatch)


                    curRow = curRow.replace(expiryReplaceStr, symbol)
                    if hideDisplayingPrice:
                        curRow = curRow.replace(expiryPriceReplaceStr, '')
                    else:
                        curRow = curRow.replace(expiryPriceReplaceStr, str(price))

                    colorSchema = ' '

                    if self.sigDecimalClose == self.round_decimal_places(float(price)):
                        colorSchema = ' bg-success text-white '
                    elif self.sigDecimalCloseComplement == self.round_decimal_places(float(price)):
                        colorSchema = ' bg-primary text-white '


                        

                    curRow = curRow.replace(expiryColorSchemaReplaceStr, colorSchema)

                i = i + 1

            htmlCode = htmlCode + curRow



        return htmlCode

    def getDebug(self):
        return str(self.debug)



if __name__== "__main__":

    returnDict = {}
    returnDict['status'] = 'OK'
    returnDict['remarks'] = ''
    returnDict['htmlCode'] = ''

    try:
        helper = GETDATA(sys.argv[1])
    except Exception as e:
        returnDict['status'] = 'KO'
        returnDict['remarks'] = str(e)
        print (json.dumps(returnDict))
        sys.exit()

    try:
        returnDict['htmlCode'] = helper.getData()
    except Exception as e:
        returnDict['status'] = 'KO'
        returnDict['remarks'] = str(e) + ' ' + helper.getDebug()

    print (json.dumps(returnDict))


    