# This script pulls (in one hit) the data from Bromley Council Bins Data
import datetime
import re
import time
from datetime import datetime

import requests
from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
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:
            data = {"bins": []}
            headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64)"}

            uprn = kwargs.get("uprn")
            postcode = kwargs.get("postcode")
            web_driver = kwargs.get("web_driver")
            headless = kwargs.get("headless")
            driver = create_webdriver(web_driver, headless, None, __name__)
            driver.get(kwargs.get("url"))

            wait = WebDriverWait(driver, 60)
            post_code_search = wait.until(
                EC.presence_of_element_located(
                    (By.XPATH, f"//input[contains(@class, 'searchAddress')]")
                )
            )
            post_code_search.send_keys(postcode)

            submit_btn = wait.until(
                EC.presence_of_element_located(
                    (By.XPATH, f"//button[contains(@class, 'searchAddressButton')]")
                )
            )

            submit_btn.send_keys(Keys.ENTER)

            address_link = wait.until(
                EC.presence_of_element_located(
                    (By.XPATH, f'//a[contains(@data-uprn,"{uprn}")]')
                )
            )

            address_link.send_keys(Keys.ENTER)

            address_results = wait.until(
                EC.presence_of_element_located(
                    (By.CLASS_NAME, "your-collection-schedule-container")
                )
            )

            # Make a BS4 object
            soup = BeautifulSoup(driver.page_source, features="html.parser")
            data = {"bins": []}

            # Get the current month and year
            current_month = datetime.now().month
            current_year = datetime.now().year

            # Function to extract collection data
            def extract_collection_data(collection_div, collection_type):
                if collection_div:
                    date_element = (
                        collection_div.find(class_="recycling-collection-day-numeric")
                        or collection_div.find(class_="refuse-collection-day-numeric")
                        or collection_div.find(class_="garden-collection-day-numeric")
                    )
                    month_element = (
                        collection_div.find(class_="recycling-collection-month")
                        or collection_div.find(class_="refuse-collection-month")
                        or collection_div.find(class_="garden-collection-month")
                    )

                    if date_element and month_element:
                        collection_date = date_element.get_text(strip=True)
                        collection_month = month_element.get_text(strip=True)

                        # Combine month, date, and year into a string
                        date_string = (
                            f"{collection_date} {collection_month} {current_year}"
                        )

                        try:
                            # Convert the date string to a datetime object
                            collection_date_obj = datetime.strptime(
                                date_string, "%d %B %Y"
                            )

                            # Check if the month is ahead of the current month
                            if collection_date_obj.month >= current_month:
                                # If the month is ahead, use the current year
                                formatted_date = collection_date_obj.strftime(
                                    date_format
                                )
                            else:
                                # If the month is before the current month, use the next year
                                formatted_date = collection_date_obj.replace(
                                    year=current_year + 1
                                ).strftime(date_format)
                            # Create a dictionary for each collection entry
                            dict_data = {
                                "type": collection_type,
                                "collectionDate": formatted_date,
                            }

                            # Append dictionary data to the 'bins' list in the 'data' dictionary
                            data["bins"].append(dict_data)

                        except ValueError as e:
                            # Handle the case where the date format is invalid
                            formatted_date = "Invalid Date Format"

            # Extract Recycling collection data
            extract_collection_data(
                soup.find(
                    class_="container-fluid RegularCollectionDay"
                ).find_next_sibling("div"),
                "Recycling",
            )

            # Extract Refuse collection data
            for refuse_div in soup.find_all(
                class_="container-fluid RegularCollectionDay"
            ):
                extract_collection_data(refuse_div, "Refuse")

            # Extract Garden Waste collection data
            extract_collection_data(
                soup.find(class_="container-fluid gardenwasteCollectionDay"),
                "Garden Waste",
            )

            # Print the extracted data
        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
