import time

from bs4 import BeautifulSoup
from dateutil.relativedelta import relativedelta
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select

from uk_bin_collection.uk_bin_collection.common import *
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass


class CouncilClass(AbstractGetBinDataClass):
    """
    Concrete classes have to implement all abstract operations of the
    base class. They can also override some operations with a default
    implementation.
    """

    def parse_data(self, page: str, **kwargs) -> dict:
        driver = None
        try:
            page = "https://www.midandeastantrim.gov.uk/resident/waste-recycling/collection-dates/"

            # Assign user info
            user_postcode = kwargs.get("postcode")
            # not used: user_paon = kwargs.get("paon")
            web_driver = kwargs.get("web_driver")
            headless = kwargs.get("headless")

            # Create Selenium webdriver
            options = webdriver.ChromeOptions()
            options.add_experimental_option("excludeSwitches", ["enable-logging"])
            driver = create_webdriver(web_driver, headless, None, __name__)

            driver.get(page)

            time.sleep(5)
            number = 0
            driver.switch_to.frame(number)
            # Enter postcode in text box and wait
            inputElement_pc = driver.find_element(By.ID, "txtAjaxSearch")
            inputElement_pc.send_keys(user_postcode)

            time.sleep(5)

            # Submit address information and wait - selecting the top one only
            # if it is an exact match then it will go straight to the results
            try:
                button = driver.find_element(By.XPATH, '//*[@id="show-button-0"]')
                driver.execute_script("arguments[0].click();", button)
            except NoSuchElementException:
                pass

            time.sleep(4)

            # Read next collection information
            page = driver.find_element(By.ID, "divCalendarGraphics").get_attribute(
                "outerHTML"
            )

            # Make a BS4 object - remove bold tags and add @ so we can split the lines later
            soup = BeautifulSoup(
                page.strip()
                .replace("<b>", "")
                .replace("</b>", "")
                .replace("<br>", "@"),
                features="html.parser",
            )
            soup.prettify()

            # Data to return
            data = {"bins": []}

            # Valid bin types
            binTypes = ["Refuse", "Garden"]

            # Value to create dict for bin values
            keys, values = [], []

            # Loop though html for text containing bins
            # example of html (bold tags removed above)
            # <div id="divCalendarGraphics">
            # <br>  <b>Refuse</b>: Tue 14 Nov then every alternate  Tue<br><b>Recycling</b>: No Recycling waste collection for this address<br><b>Garden</b>: Tue 21 Nov then every alternate  Tue<br><img src="img/Gif-Spacer.gif" alt="spacer" height="1" width="30">
            # split by br tag and take first 4 splits
            lines = soup.text.split("@", 4)
            for line in lines[1:4]:
                keys.append(line.split(":")[0].strip())
                # strip out the day and month from the text
                values.append(line.split(":")[1].strip().split(" ")[:3])

            # Create dict for bin name and string dates
            binDict = dict(zip(keys, values))

            # Process dict for valid bin types
            for bin in list(binDict):
                if bin in binTypes:
                    # Convert date - no year value so take it from todays date
                    if binDict[bin][0] == "Tomorrow":
                        date = datetime.today() + relativedelta(days=1)
                    elif binDict[bin][0] == "Today":
                        date = datetime.today()
                    else:
                        date = datetime.strptime(
                            " ".join(binDict[bin][1:]), "%d %b"
                        ).replace(year=datetime.today().year)
                        # if the date is in the past then it means the collection is next year so add a year
                        if date < datetime.today():
                            date = date + relativedelta(years=1)

                    # Set bin data
                    dict_data = {
                        "type": bin,
                        "collectionDate": date.strftime(date_format),
                    }
                    data["bins"].append(dict_data)

        # Quit Selenium webdriver to release session
        except Exception as e:
            # Here you can log the exception if needed
            print(f"An error occurred: {e}")
            # Optionally, re-raise the exception if you want it to propagate
            raise
        finally:
            # This block ensures that the driver is closed regardless of an exception
            if driver:
                driver.quit()
        return data
