# This files contains your custom actions which can be used to run
# custom Python code.
#
# See this guide on how to implement these action:
# https://rasa.com/docs/rasa/custom-actions


# This is a simple example for a custom action which utters "Hello World!"
import re
from typing import Any, Text, Dict, List
from rasa_sdk import Action, Tracker, FormValidationAction
from rasa_sdk.events import SlotSet, EventType
from rasa_sdk.executor import CollectingDispatcher
import webbrowser
from rasa_sdk.events import AllSlotsReset
from rasa_sdk.events import Restarted
from rasa_sdk.types import DomainDict
from actions.email_utility import SMTPUtility

import requests


def hit_api(payload):
    try:
        url = "http://rasa-flask:2526/insert_into_mongo"

        headers = {
            'Content-Type': 'application/json'
        }

        response = requests.request("POST", url, headers=headers, data=payload)
    except Exception as e:
        print(e)


class DemoSlotReset(Action):
    def name(self) -> Text:
        return "demo_slot_reset"

    def run(self, dispatcher, tracker, domain):
        return [SlotSet("demo", None)]


class UserDetailsForm(FormValidationAction):
    def name(self) -> Text:
        return "user_details_form"

    def run(
            self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        required_slots = ["name", "email", "number", "company", "demo"]

        for slot_name in required_slots:
            if tracker.slots.get(slot_name) is None:
                # The slot is not filled yet. Request the user to fill this slot next.
                return [SlotSet("requested_slot", slot_name)]

        # All slots are filled.
        return [SlotSet("requested_slot", None)]


class ActionSubmit(FormValidationAction):
    def name(self) -> Text:
        return "action_submit"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:
        dispatcher.utter_message("Thanks for providing the details our team of experts will contact you for "
                                 "scheduling the demo.")
        body = "\"name\":\"{0}\",\"email\":\"{1}\",\"phoneNumber\":\"{2}\"," \
               "\"product\":\"{3}\",\"company\":\"{4}\",\"request\":\"{5}\"".format(str(tracker.get_slot("name")),
                                                                                    str(tracker.get_slot("email")),
                                                                                    str(tracker.get_slot("number")),
                                                                                    str(tracker.get_slot("demo")),
                                                                                    str(tracker.get_slot("company")),
                                                                                    "Requesting a Demo of " + str(
                                                                                        tracker.get_slot("demo")))
        payload = "{" + body + "}"
        hit_api(payload)


class CallForm(FormValidationAction):
    def name(self) -> Text:
        return "call_form"

    def run(
            self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        required_slots = ["name", "email", "number", "company"]

        for slot_name in required_slots:
            if tracker.slots.get(slot_name) is None:
                # The slot is not filled yet. Request the user to fill this slot next.
                return [SlotSet("requested_slot", slot_name)]

        # All slots are filled.
        return [SlotSet("requested_slot", None)]


class CallSubmit(FormValidationAction):
    def name(self) -> Text:
        return "call_submit"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:
        dispatcher.utter_message("Thanks for providing the details our team of experts will reach out to you in "
                                 "a short while.")
        body = "\"name\":\"{0}\",\"email\":\"{1}\",\"phoneNumber\":\"{2}\"," \
               "\"company\":\"{3}\",\"request\":\"{4}\"".format(str(tracker.get_slot("name")),
                                                                str(tracker.get_slot("email")),
                                                                str(tracker.get_slot("number")),
                                                                str(tracker.get_slot("company")),
                                                                "Requesting for a Call Back")
        payload = "{" + body + "}"
        hit_api(payload)


class QueryForm(FormValidationAction):
    def name(self) -> Text:
        return "query_form"

    def run(
            self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        required_slots = ["name", "email", "number", "company", "query"]

        for slot_name in required_slots:
            if tracker.slots.get(slot_name) is None:
                # The slot is not filled yet. Request the user to fill this slot next.
                return [SlotSet("requested_slot", slot_name)]

        # All slots are filled.
        return [SlotSet("requested_slot", None)]


class QuerySubmit(FormValidationAction):
    def name(self) -> Text:
        return "query_submit"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:
        dispatcher.utter_message("Your query has been registered with us. Our team of experts will follow up with a "
                                 "resolution soon")
        body = "\"name\":\"{0}\",\"email\":\"{1}\",\"phoneNumber\":\"{2}\"," \
               "\"query\":\"{3}\",\"company\":\"{4}\",\"request\":\"{5}\"".format(str(tracker.get_slot("name")),
                                                                                  str(tracker.get_slot("email")),
                                                                                  str(tracker.get_slot("number")),
                                                                                  str(tracker.get_slot("query")),
                                                                                  str(tracker.get_slot("company")),
                                                                                  "Have a Query")
        payload = "{" + body + "}"
        hit_api(payload)


class ActionRestarted(Action):
    def name(self):
        return 'action_restarted'

    def run(self, dispatcher, tracker, domain):
        return [Restarted()]


class ActionSlotReset(Action):
    def name(self):
        return 'action_slot_reset'

    def run(self, dispatcher, tracker, domain):
        return [AllSlotsReset()]


class ActionSessionId(Action):
    def name(self) -> Text:
        return "action_session_id"

    async def run(
            self, dispatcher, tracker: Tracker, domain: Dict[Text, Any]
    ) -> List[Dict[Text, Any]]:
        conversation_id = tracker.sender_id
        dispatcher.utter_message("The conversation id is {}".format(conversation_id))
        return []


class EmailForm(Action):
    def name(self) -> Text:
        return "email_form"

    def run(
            self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        required_slots = ["email"]

        for slot_name in required_slots:
            if tracker.slots.get(slot_name) is None:
                # The slot is not filled yet. Request the user to fill this slot next.
                return [SlotSet("requested_slot", slot_name)]

        return [SlotSet("requested_slot", None)]


class EmailSubmit(FormValidationAction):
    def name(self) -> Text:
        return "email_submit"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:
        # dispatcher.utter_message("Your Details: " + "\n Email: " + tracker.get_slot("email"))
        dispatcher.utter_message("You have successfully subscribed to our newsletter")
        body = "\"email\":\"{0}\",\"request\":\"{1}\"".format(str(tracker.get_slot("email")), "Email Signup")
        payload = "{" + body + "}"
        hit_api(payload)


class ValidateEmailForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_email_form"

    def validate_email(
            self,
            slot_value: Any,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate cuisine value."""
        my_list = str(slot_value).lower().split(" ")
        for i in my_list:
            if re.match(r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?", str(i)):
                return {'email': str(i)}

        dispatcher.utter_message(text="The email you have entered is invalid")
        return {'email': None}


class ValidateUserDetailsForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_user_details_form"

    def validate_demo(
            self,
            slot_value: Any,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: DomainDict,
    ) -> Dict[Text, Any]:
        myval = ['mlens', 'ilens', 'glens']
        mylist = str(slot_value.lower()).split(" ")
        a = set(myval)
        b = set(mylist)
        if a & b:
            return {'demo': list(a & b)[0]}
        else:
            dispatcher.utter_message("Sorry we dont have support for that product.")
            return {'demo': None}

    def validate_email(
            self,
            slot_value: Any,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate cuisine value."""

        my_list = str(slot_value).lower().split(" ")
        for i in my_list:
            if re.match(r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?", str(i)):
                return {'email': str(i)}

        dispatcher.utter_message(text="The email you have entered is invalid")
        return {'email': None}

    def validate_number(
            self,
            slot_value: Any,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate cuisine value."""

        my_list = str(slot_value).lower().split(" ")
        for i in my_list:
            if re.match(r"^(((\+?\(91\))|0|((00|\+)?91))-?)?[7-9]\d{9}$", str(i)):
                return {'number': str(i)}
        dispatcher.utter_message(text="The mobile you have entered is invalid")
        return {'number': None}


class ValidateQueryForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_query_form"

    def validate_email(
            self,
            slot_value: Any,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate cuisine value."""

        my_list = str(slot_value).lower().split(" ")
        for i in my_list:
            if re.match(r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?", str(i)):
                return {'email': str(i)}

        dispatcher.utter_message(text="The email you have entered is invalid")
        return {'email': None}

    def validate_number(
            self,
            slot_value: Any,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate cuisine value."""

        my_list = str(slot_value).lower().split(" ")
        for i in my_list:
            if re.match(r"^(((\+?\(91\))|0|((00|\+)?91))-?)?[7-9]\d{9}$", str(i)):
                return {'number': str(i)}
        dispatcher.utter_message(text="The mobile you have entered is invalid")
        return {'number': None}


class ValidateCallForm(FormValidationAction):
    def name(self) -> Text:
        return "validate_call_form"

    def validate_email(
            self,
            slot_value: Any,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate cuisine value."""

        my_list = str(slot_value).lower().split(" ")
        for i in my_list:
            if re.match(r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?", str(i)):
                return {'email': str(i)}

        dispatcher.utter_message(text="The email you have entered is invalid")
        return {'email': None}

    def validate_number(
            self,
            slot_value: Any,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate cuisine value."""

        my_list = str(slot_value).lower().split(" ")
        for i in my_list:
            if re.match(r"^(((\+?\(91\))|0|((00|\+)?91))-?)?[7-9]\d{9}$", str(i)):
                return {'number': str(i)}
        dispatcher.utter_message(text="The mobile you have entered is invalid")
        return {'number': None}
