import ssl
from datetime import datetime
from typing import Dict, List, Optional, Text
import logging

logger = logging.getLogger(__name__)

DATE_FORMAT = "%d %B, %Y"


class CommunityEvent:
    def __init__(self, name, city, country, formatted_date, date, link) -> None:
        self.name = name
        self.city = city
        self.country = country
        self.formatted_date = formatted_date
        self.date = date
        self.link = link

    def __repr__(self) -> Text:
        return "{} ({}): {} ({})".format(
            self.name, self.city, self.formatted_date, self.date
        )

    @classmethod
    def from_html(cls, html) -> Optional["CommunityEvent"]:
        try:
            city = html.contents[0]
            link = html.contents[3].get("href")
            name = html.contents[3].contents[0]
            date_as_string = html.contents[8]
            country = get_country_for(city)
            date = parse_community_date(date_as_string).date()
        except Exception as e:
            logger.warning(f"Error when trying to parse event details from html.\n{e}")
            return None

        return cls(
            name.strip(),
            city.strip(),
            country,
            date_as_string.strip(),
            date,
            link.strip(),
        )

    def name_as_link(self) -> Text:
        return "[{}]({})".format(self.name, self.link)

    def as_kwargs(self) -> Dict[Text, Text]:
        return {
            "event_name": self.name_as_link(),
            "event_location": self.city,
            "event_date": self.formatted_date,
        }


def parse_community_date(date_string: Text) -> datetime:

    dates = date_string.split("-")

    try:
        return datetime.strptime(dates[-1].strip(), DATE_FORMAT)
    except Exception as e:
        logger.warning(e)
        return datetime.min


def get_community_events() -> List[CommunityEvent]:
    """Returns list of community events sorted ascending by their date."""
    from bs4 import BeautifulSoup
    import requests as r
    import datetime

    response = r.get("https://rasa.com/community/join/")

    if response.status_code == 200:
        community_page = response.content

        soup = BeautifulSoup(community_page, "html.parser")

        events = soup.find("ul", attrs={"id": "events-list"}).find_all("li")
        # [1].find("ul").find_all("li")
        events = [CommunityEvent.from_html(e) for e in events]

        now = datetime.date.today()
        events = [e for e in events if e is not None and e.date >= now]
        return sorted(events, key=lambda e: e.date)

    return []


def get_country_for(city: Text) -> Optional[Text]:
    from geopy.geocoders import Nominatim

    ssl_context = ssl.create_default_context()
    ssl_context.check_hostname = False
    ssl_context.verify_mode = ssl.CERT_NONE

    geo_locator = Nominatim(ssl_context=ssl_context)
    location = geo_locator.geocode(city, language="en", addressdetails=True)

    if location:
        return location.raw["address"].get("country")

    return None