"""
Slack chat-bot Lambda handler.
"""
import os
import logging
import urllib
import urllib.request
import calendar
from datetime import datetime


# Grab the Bot OAuth token from the environment.
BOT_TOKEN = os.environ["BOT_TOKEN"]

# Define the URL of the targeted Slack API resource.
# We'll send our replies there.
SLACK_URL = "https://slack.com/api/chat.postMessage"
ASSUME_30_DAYS = 360
String_360 = "360"
LEAPYEAR_DAYS = 366
String_Leapyear = "366"
ANNUAL_DAYS = 365
String_annual = "365"
DAYS_30 = 30
String_30 = "30"
TOTAL_MONTHS_YEAR = 12
String_12 = "12"
DAYS_31 = 31
String_31 = "31"
Bracket_open = "("
Bracket_close = ")"
Plus_sign =" + "
Product_sign = " * "
Div_sign = " / "
String_1 = "1"

def lambda_handler(data, context):
    """Handle an incoming HTTP request from a Slack chat-bot.
    """
    logging.warn(data)
    if "challenge" in data:
        return data["challenge"]
    
    # Grab the Slack event data.
    slack_event = data['event']
    
    # We need to discriminate between events generated by 
    # the users, which we want to process and handle, 
    # and those generated by the bot.

    if "bot_id" in slack_event:
        logging.warn("Ignore bot event")
    else:
        # Get the text of the message the user sent to the bot,
        # and reverse it.
        text = slack_event["text"]
        splittext = text.split("|")
        #Start Date
        startdate = str(splittext[:1]).strip('[]').strip('\'"')
        #End Date
        Enddate = str(splittext[1:2]).strip('[]').strip('\'"')
        #Amount
        Amount = str(splittext[2:3]).strip('[]').strip('\'"')
        #reversed_text = startdate.strip('[]') + Enddate.strip('[]') + Amount.strip('[]')
        
        ServiceEnd = datetime.strptime(Enddate,'%Y-%m-%d')
        Servicestart = datetime.strptime(startdate,'%Y-%m-%d')
        #ISITLEAP = Servicestart.year
        Diffdays = ServiceEnd - Servicestart
        TotalDays = Diffdays.days + 1
        Noofdays = str(TotalDays)
    
        def diff_month(d1, d2):
            return (d1.year - d2.year) * 12 + (d1.month - d2.month)
        tMonths = diff_month(ServiceEnd,Servicestart)
        tMonths = tMonths
        DiffMonth = str(tMonths)
        def leapyear(d1):
            if(d1.year%4==0 and d1.year%100!=0 or d1.year%400==0):
                return True
            else:
                return False
        ActualdaysinMonth = calendar.monthrange(Servicestart.year,Servicestart.month)[1]
        ProratedDays = ServiceEnd.day
        AmountforProration = float(Amount)
        YearlyProration = (tMonths/TOTAL_MONTHS_YEAR)
        #BD30
        #Monthly Billing Proration
        
        if TotalDays > 31:
            MTotalAmountBMAD = AmountforProration *(YearlyProration + ((ProratedDays/ActualdaysinMonth)))
            MBDADStr = Amount+Product_sign+Bracket_open + str(tMonths)+ Div_sign + String_12+Bracket_close 
            MBDADStr = MBDADStr + Plus_sign + str(ProratedDays) + Div_sign + str(ActualdaysinMonth) + Bracket_close
            YTotalAmountBMAD = AmountforProration *(YearlyProration + ((ProratedDays/ActualdaysinMonth)*(1/TOTAL_MONTHS_YEAR)))
            YBDADStr = Amount + Product_sign + Bracket_open + str(tMonths)+ Div_sign + String_12+Bracket_close
            YBDADStr = YBDADStr + Plus_sign + Bracket_open + str(ProratedDays) +Div_sign + str(ActualdaysinMonth) +Bracket_close
        else:
            MTotalAmountBMAD = AmountforProration * (TotalDays/ActualdaysinMonth)
            MBMADStr = Amount + Product_sign + Bracket_open + str(TotalDays) + Div_sign + str(ActualdaysinMonth) + Bracket_close 
            YTotalAmountBMAD = AmountforProration *((TotalDays/ActualdaysinMonth)*(1/TOTAL_MONTHS_YEAR))
            YBMADStr = Amount+ Product_sign + Bracket_open + Bracket_open + str(TotalDays)+Div_sign+str(ActualdaysinMonth)+Bracket_close
            YBMADStr = YBMADStr + Product_sign + Bracket_open +String_1+Div_sign+ String_12+ Bracket_close+Bracket_close
        MAmountBMAD = str(round(MTotalAmountBMAD,2))
        YAmountBMAD = str(round(YTotalAmountBMAD,2))

        if TotalDays > 31:
            MTotalAmountBM30 = AmountforProration * (YearlyProration + (ProratedDays/DAYS_30))
            MBM30Str = Amount + Product_sign+ Bracket_open + str(tMonths)+ Div_sign + String_12+Bracket_close
            MBM30Str = MBM30Str + Plus_sign + Bracket_open + str(ProratedDays) + Div_sign + String_30 + Bracket_close+ Bracket_close
            YTotalAmountBM30 = AmountforProration * (YearlyProration + ((ProratedDays/DAYS_30)*(1/TOTAL_MONTHS_YEAR)))
            YBM30Str = Amount + Product_sign+ Bracket_open + str(tMonths)+ Div_sign + String_12+Bracket_close
            YBM30Str = YBM30Str + Product_sign + Bracket_open + Bracket_open + str(ProratedDays)+Div_sign+String_30+Bracket_close
            YBM30Str = YBM30Str + Product_sign + Bracket_open +String_1+Div_sign+ String_12+ Bracket_close+Bracket_close
        else:
            MTotalAmountBM30 = AmountforProration * (TotalDays/DAYS_30)
            MBM30Str = Amount + Product_sign + Bracket_open + str(TotalDays) + Div_sign + String_30 + Bracket_close
            YTotalAmountBM30 = AmountforProration * ((TotalDays/DAYS_30)*(1/TOTAL_MONTHS_YEAR))
            YBM30Str = Amount + Product_sign + Bracket_open + Bracket_open + str(TotalDays)+Div_sign+String_30+Bracket_close
            YBM30Str = YBM30Str + Product_sign + Bracket_open +String_1+Div_sign+ String_12+ Bracket_close+Bracket_close
        MAmountBM30 = str(round(MTotalAmountBM30,2))
        YAmountBM30 = str(round(YTotalAmountBM30,2))

        if TotalDays > 31:
            MTotalAmountBDAD = AmountforProration * ((ProratedDays)/ActualdaysinMonth)
            MBDADStr = Amount + Product_sign + Bracket_open + Noofdays + Div_sign + str(ActualdaysinMonth) + Bracket_close
        else:
            MTotalAmountBDAD = AmountforProration * ((TotalDays)/ActualdaysinMonth)
            MBDADStr = Amount + Product_sign + Bracket_open + str(TotalDays) + Div_sign + str(ActualdaysinMonth) + Bracket_close
        
        MAmountBDAD = str(round(MTotalAmountBDAD,2))

        if leapyear(Servicestart):
            YTotalAmountBDAD = AmountforProration * ((TotalDays)/LEAPYEAR_DAYS)
            YBDADStr = Amount + Product_sign + Bracket_open + Noofdays + Div_sign + String_Leapyear + Bracket_close
        else:
            YTotalAmountBDAD = AmountforProration * ((TotalDays)/ANNUAL_DAYS)
            YBDADStr = Amount + Product_sign + Bracket_open + Noofdays + Div_sign + String_annual + Bracket_close
        YAmountBDAD = str(round(YTotalAmountBDAD,2))

        if TotalDays > 31:
            MTotalAmountBD30 = AmountforProration * ((ProratedDays)/DAYS_30)
            MBD30Str = Amount + Product_sign + Bracket_open + str(ProratedDays) + Div_sign + String_30 + Bracket_close
        else:
            MTotalAmountBD30 = AmountforProration * ((TotalDays)/DAYS_30)
            MBD30Str = Amount + Product_sign + Bracket_open + Noofdays + Div_sign + String_30 + Bracket_close
        MAmountBD30 = str(round(MTotalAmountBD30,2))

        YTotalAmountBD30 = AmountforProration * ((TotalDays)/ASSUME_30_DAYS)
        YBD30Str = Amount + Product_sign + Bracket_open + Noofdays + Div_sign + String_360 + Bracket_close
        YAmountBD30 = str(round(YTotalAmountBD30,2))

        Proration_Charges = "Service Start Date: " + startdate + "\n "
        Proration_Charges = Proration_Charges + "Service End Date:"+ Enddate 
        Proration_Charges = Proration_Charges + "\n "+ "Amount: " + Amount 
        Proration_Charges = Proration_Charges +"\n  Days: " + Noofdays 
        Proration_Charges = Proration_Charges + "\n Months:"+ DiffMonth 
        Proration_Charges = Proration_Charges + "\n BMAD - Monthly:" + MAmountBMAD
        Proration_Charges = Proration_Charges + "\n BM30 - Monthly:" + MAmountBM30        
        Proration_Charges = Proration_Charges + "\n BDAD - Monthly:" + MAmountBDAD 
        Proration_Charges = Proration_Charges + "\n BD30 - Monthly:" + MAmountBD30 
        Proration_Charges = Proration_Charges +"\n BMAD Calculations: "
        Proration_Charges = Proration_Charges + MBMADStr       
        Proration_Charges = Proration_Charges + "\n BD30 Calculations: "
        Proration_Charges = Proration_Charges + MBD30Str
        Proration_Charges = Proration_Charges +"\n BDAD Calculations: "
        Proration_Charges = Proration_Charges + MBDADStr   
        Proration_Charges = Proration_Charges +"\n BM30 Calculations: "
        Proration_Charges = Proration_Charges + MBM30Str   
        Proration_Charges = Proration_Charges + "\n BMAD - Annual:" + YAmountBMAD
        Proration_Charges = Proration_Charges + "\n BM30 - Annual:" + YAmountBM30
        Proration_Charges = Proration_Charges + "\n BDAD - Annual:" + YAmountBDAD 
        Proration_Charges = Proration_Charges + "\n BD30 - Annual:" + YAmountBD30 
        Proration_Charges = Proration_Charges +"\n BMAD Calculations: "
        Proration_Charges = Proration_Charges + YBMADStr       
        Proration_Charges = Proration_Charges +"\n BM30 Calculations: "
        Proration_Charges = Proration_Charges + YBM30Str   
        Proration_Charges = Proration_Charges +"\n BDAD Calculations: "
        Proration_Charges = Proration_Charges + YBDADStr   
        Proration_Charges = Proration_Charges + "\n BD30 Calculations: "
        Proration_Charges = Proration_Charges + YBD30Str

        # Get the ID of the channel where the message was posted.
        channel_id = slack_event["channel"]
       
        # We need to send back three pieces of information:
        #     1. The reversed text (text)
        #     2. The channel id of the private, direct chat (channel)
        #     3. The OAuth token required to communicate with 
        #        the API (token)
        # Then, create an associative array and URL-encode it, 
        # since the Slack API doesn't not handle JSON (bummer).
        
        data = urllib.parse.urlencode(
            (
                ("token", BOT_TOKEN),
                ("channel", channel_id),
                ("text", Proration_Charges)
            )
        )
        
        data = data.encode("ascii")
            
        # Construct the HTTP request that will be sent to the Slack API.
        request = urllib.request.Request(
            SLACK_URL, 
            data=data, 
            method="POST"
        )
            # Add a header mentioning that the text is URL-encoded.
        request.add_header(
            "Content-Type", 
            "application/x-www-form-urlencoded"
        )
            
            # Fire off the request!
        urllib.request.urlopen(request).read()
    
        # Everything went fine.
        return "200 OK"
