import time
from datetime import datetime

from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.wait import WebDriverWait

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

# import the wonderful Beautiful Soup and the URL grabber


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://my.portsmouth.gov.uk/en/AchieveForms/?form_uri=sandbox-publish://AF-Process-26e27e70-f771-47b1-a34d-af276075cede/AF-Stage-cd7cc291-2e59-42cc-8c3f-1f93e132a2c9/definition.json&redirectlink=%2F&cancelRedirectLink=%2F"

            data = {"bins": []}

            user_uprn = kwargs.get("uprn")
            user_postcode = kwargs.get("postcode")
            web_driver = kwargs.get("web_driver")
            headless = kwargs.get("headless")
            check_uprn(user_uprn)
            check_postcode(user_postcode)
            # Create Selenium webdriver
            driver = create_webdriver(web_driver, headless, None, __name__)
            driver.get(page)

            # If you bang in the house number (or property name) and postcode in the box it should find your property

            iframe_presense = WebDriverWait(driver, 30).until(
                EC.presence_of_element_located((By.ID, "fillform-frame-1"))
            )

            driver.switch_to.frame(iframe_presense)
            wait = WebDriverWait(driver, 60)
            inputElement_postcodesearch = wait.until(
                EC.element_to_be_clickable((By.NAME, "postcode_search"))
            )

            inputElement_postcodesearch.send_keys(user_postcode)
            lookupAddress_btn = wait.until(
                EC.element_to_be_clickable((By.ID, "lookupAddress"))
            )

            lookupAddress_btn.click()

            # Wait for the 'Select your property' dropdown to appear and select the first result
            dropdown = wait.until(
                EC.element_to_be_clickable((By.NAME, "Choose_Address"))
            )

            dropdown_options = wait.until(
                EC.presence_of_element_located((By.CLASS_NAME, "lookup-option"))
            )
            time.sleep(1)
            # Create a 'Select' for it, then select the first address in the list
            # (Index 0 is "Make a selection from the list")
            dropdownSelect = Select(dropdown)
            dropdownSelect.select_by_value(str(user_uprn))

            h4_element = wait.until(
                EC.presence_of_element_located(
                    (By.XPATH, "//h4[contains(text(), 'next 10 collection dates')]")
                )
            )

            soup = BeautifulSoup(driver.page_source, features="html.parser")
            # Define your XPath
            elements_with_data_field_name = soup.find_all(
                lambda tag: tag.has_attr("data-field-name")
                and tag["data-field-name"].startswith("html")
            )
            if elements_with_data_field_name:
                for element in elements_with_data_field_name:
                    # Extract h4 text from the current element
                    h4_text = (
                        element.find("h4").get_text(strip=True)
                        if element.find("h4")
                        else None
                    )

                    # Process the data (dates) in the current element (p tags)

                    if h4_text:
                        if "next 10" in h4_text:
                            data_paragraphs = element.find_all("p") if element else []

                            # Extract dates from the first <p> tag (assuming dates are in the first <p> tag)
                            dates_paragraph = (
                                data_paragraphs[0] if len(data_paragraphs) > 0 else None
                            )
                            dates = (
                                dates_paragraph.find_all(string=True, recursive=False)
                                if dates_paragraph
                                else []
                            )

                            for date in dates:
                                data["bins"].append(
                                    {
                                        "type": h4_text.split(" - ")[0],
                                        "collectionDate": datetime.strptime(
                                            re.sub(
                                                r"[^a-zA-Z0-9,\s]", "", date
                                            ).strip(),
                                            "%A %d %B %Y",
                                        ).strftime("%d/%m/%Y"),
                                    }
                                )
        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
