import random
import features
import json

api = features.API()
debug = False

def handle_command(sender, message):
    state = api.get_user_state(sender)
    for command in commands:
        if message.find(command) == 0:
            result = commands[command](state, message, sender)
            return result
    if len(state) > 0:
        if debug == 1:
            return commands[state[0]](state, message, sender)
        try:
            result = commands[state[0]](state, message, sender)
            return result
        except Exception as e:
            if __name__ != '__main__':
                state = []
                api.update_user_state(sender, state)
            return {
                "response": f"⚠️Error⚠️\n{e}"
            }

    return {
        "response": "",
    }


def get_faq_string():
    return api.get_faq_string()


def nevermind(state, message, sender):
    api.update_user_state(sender, [])
    return {
        "response": "starting over."
    }

# faq


def get_faq(state, message, sender):
    if len(state) == 0:
        return {
            "response": api.get_faq_string()
        }
    return {
        "response": api.get_faq_string()
    }


def add_question(state, message, sender):
    if len(state) == 0:
        api.update_user_state(sender, ["!add question"])
        return {
            'response': "Please enter the question title."
        }
    elif len(state) == 1:
        state.append(message)
        api.update_user_state(sender, state)
        return {
            'response': 'Please enter the answer to the question.'
        }
    elif len(state) == 2:
        state.append(message)
        api.update_user_state(sender, state)
        state = api.get_user_state(sender)
        return {
            'response': f"Your question is:\n---\n# {state[1]}\n{state[2]}\n\n---\nIf this is what you want respond with `confirm`\n If you'd like to start over respond with `restart`\n Respond with `nevermind` to cancel entirely"
        }
    elif len(state) == 3:
        if message == 'confirm':
            api.add_question({
                'question': state[1],
                'answer': state[2]
            })
            api.update_user_state(sender, [])
            return {
                'response': 'Question added.'
            }
        elif message == 'restart':
            api.update_user_state(sender, ['!add question'])
            return {
                'response': 'Please enter the question title.'
            }
        else:
            return {
                'response': f"Your question is:\n# {state[1]}\n{state[2]}\n\nIf this is what you want respond with `confirm`\n If you'd like to start over respond with `restart`\n Respond with `nevermind` to cancel entirely"
            }

    return {
        'response': None
    }


def update_question(state, message, sender):
    if len(api.data['faq']['questions']) == 0:
        api.update_user_state(sender, [])
        return {
            'response': "No questions registered."
        }
    elif len(state)==0:
        api.update_user_state(sender,"!update question")
        return {
            "response":f"Choose a question to update:\n {api.get_faq_questions}"
        }
    return {
        'response': None,

    }


def remove_question(state, message, sender):
    if len(api.data['faq']['questions']) == 0:
        api.update_user_state(sender, [])
        return {
            'response': "No questions registered."
        }
    elif len(state)==0:
        api.update_user_state(sender,["!remove question"])
        return {
            "response":f"Choose a question to remove:\n {api.get_faq_questions()}"
        }
    elif len(state) == 1:
        try:
            int(message)
        except:
            return {"response":"Please enter a number."}
        state.append(message)
        if  int(state[1]) < len(api.data['faq']['questions']) and int(state[1]) >=0:
            if debug == True:
                api.remove_question(int(state[1]))
                api.update_user_state(sender,[])
                return {
                    'response':'Question removed'
                }
            else:
                try:
                    api.update_user_state(sender,[])
                    api.remove_question(int(state[1]))
                    return {
                        'response':'Question removed'
                    }
                except:
                    pass
                    
        api.update_user_state(sender,["!remove question"])
        return {
            'response':'Please enter the correct question #'
        }
        
        
    return {
        'response': None,

    }


def update_header(state, message, sender):
    return {
        'response': None,

    }


def remove_header(state, message, sender):
    return {
        'response': None,

    }


def update_footer(state, message, sender):
    return {
        'response': None,

    }


def remove_footer(state, message, sender):
    return {
        'response': None,

    }


def add_admin(state, message, sender):
    return {
        'response': None,

    }


def remove_admin(state, message, sender):
    return {
        'response': None,

    }

def meetings(state,message,sender):
    return {
        'response':api.appointments.list_upcoming_appointments(sender)
    }

def register_customer(state,message,sender):
    if api.appointments.is_customer(sender):
        return {'response':"Already registered."}
    if state == ['!register2']:
        return {
            'response':'What is your first name?'
        }

    if state == []:
        state = ['!register']
        api.update_user_state(sender, state)
        return {
            'response':'What is your first name?'
        }
    if len(state) == 1:
        state.append(message)
        api.update_user_state(sender, state)
        return {
            'response':'What is your last name?'
        }
    if len(state) == 2:
        state.append(message)
        api.update_user_state(sender, state)
        return {
            'response':'What is your e-mail?'
        }
    if len(state) == 3:
        state.append(message)
        api.update_user_state(sender, state)
        return {
            'response':"What is your phone number?"
        }
    if len(state) == 4:
        state.append(message)
        api.update_user_state(sender, state)
        resp = f"You've entered: `{state[1]} {state[2]} ({state[3]} / {state[4]})`\n**Is this correct?**\nIf so, respond with:Yes\nIf not, to restart respond with :No\nYou can always cancel with:nevermind"
        return {
            'response':resp
        }
    if len(state) == 5:
        if "yes" in message.lower():
            data = {
                "firstName":state[1],
                "lastName":state[2],
                "email":state[3],
                "phone":state[4],
                "notes":f"matrix:{sender}"
            }
            if sender == "admin":
                dat = json.dumps(data)
                print(f"Data:\n{dat}")
            if api.appointments.register_customer(data):
                if(state[0]=='!register2'):
                    state = ['!book']
                    api.update_user_state(sender, state)
                    return {'response':"Successfully registered.\n\n"+booking(['!book'],'',sender)['response']}
                state = []
                api.update_user_state(sender, state)
                return{'response':"Successfully registered."}
            else:
                return{'response':"Error, please try again."}
    api.update_user_state(sender, [])
    return {        
        'response':''
    }

def select_service(state,message,sender):
    if len(state) >= 2:
        return select_provider(state, message, sender)
    # ['!book','select-service']
    if message == "!book":
        return {'response':api.select_service()}
    else:
        try:
            state.append(api.appointments.get_services()[int(message)]['id'])
            api.update_user_state(sender, state)
            return booking(state, "", sender)
        except:
            return {'response':'Error selecting service\nTo cancel type:nevermind'}

def select_provider(state,message,sender):
    if len(state) >= 3:
        return select_time(state, message, sender)
    if message == "":
        return {'response':api.select_provider()}
    try:
        state.append(api.appointments.get_providers()[int(message)]['id'])
        api.update_user_state(sender, state)
        return booking(state,"",sender)
    except:
        return {'response':'Error selecting provider\nTo cancel type:nevermind'}
    

def select_time(state,message,sender):
    if len(state) >= 5:
        return booking(state, message, sender)
    api.update_data()
    # ['!book','select-time']
    if len(state) == 3:
        msg = api.select_times(state[1],state[2],message)
        if msg == False:
            return {'response':"Please enter a date you'd like to book (\"YYYY-MM-DD\" format)"}
        state.append(message)
        api.update_user_state(sender, state)
        return {'response':msg}
    if len(state) == 4:
        times = api.appointments.get_availabilities(state[1], state[2], state[3])
        if message in times:
            state.append(message)
        time = None
        try:
            time = times[int(message)-1]
            state.append(time)
            api.update_user_state(sender, state)
            return booking(state, message, sender)
        except:
            return {'response':api.select_times(state[1],state[2],state[3])}
    return {'response':error}

def booking(state,message,sender):
    if len(state) > 5:
        state = []
    if state==[]:
        state.append("!book")
        api.update_user_state(sender, state)
    """
        To book an appointment, you need (in order):
        * the customer ID (now mapped to mxid) (0?)
        * The service id (1)
        * the provider id (2)
        * the start date & time (3)
    """
    #Quick checks
    customer = api.appointments.is_customer(sender)
    if  customer == False:
        return register_customer([], "", sender)

    #Service check
    service = None
    if len(api.appointments.services) == 0:
        return {'response':"Error: there are no services"}
    if len(api.appointments.services) == 1:
        service = api.appointments.get_services()[0]
        state.append(service)
        api.update_user_state(sender, state)
        return booking(state, message, sender)
    if len(state) >= 2:
        service = state[1]  
    if service == None:
        return select_service(state, message, sender)


    #Provider check
    
    provider = None
    if len(api.appointments.providers) == 0:
        return {'response':'error: there are no providers'}
    if len(state) >= 3:
        provider = state[2]
    elif len(api.appointments.providers) == 1:
        provider = api.appointments.get_providers()[0]['id']
        if service != None:
            state.append(provider)
            api.update_user_state(sender, state)
    if provider == None:
        return select_provider(state, message, sender)

    time = None
    if len(state) == 5:
        time = state[4]
    if time == None:
        return select_time(state, message, sender)    
    data = {
        "start": state[3] + " "+ state[4]+":00",
        "customerId":int(customer),
        "providerId":int(provider),
        "serviceId":int(service)
    }
    result = api.appointments.register_appointment(data)
    if result != False:
        state = []
        api.update_user_state(sender, state)
        return{'response':'Successfully registered appointment!'}
    else:
        state = []
        api.update_user_state(sender, state)
        print(result)
        return{'response':"Error: please try again"}
    
    return{'response':"Error: please try again"}
    

def services(state,message,sender):
    return {
        'response':api.list_services()
    }

commands = {
    "nevermind": nevermind,
    "!faq": get_faq,
    "!add question": add_question,
    "!remove question": remove_question,
    "!update question": update_question,
    "!update header": update_header,
    "!remove header": remove_header,
    "!update footer": update_footer,
    "!remove footer": remove_footer,
    "!add admin": add_admin,
    "!remove admin": remove_admin,
    "!meetings":meetings,
    "!register":register_customer,
    "!register2":register_customer,
    "!book":booking,
    "!services":services

}


if __name__ == '__main__':
    user = "admin"
    msg = ""
    debug = True
    while msg != "exit":
        msg = input("user:")
        print("bot:"+handle_command(user, msg)['response'])
        # print("state:",user)