from pathlib import Path
from typing import List

import scrapy
from scrapy.selector import Selector

from coffee_roaster_scrapers.items import CoffeeItem
from coffee_roaster_scrapers.utils.normalizer import extract_country


class KafferavenSpider(scrapy.Spider):  # type: ignore
    name = "kafferaven"
    start_urls = ["https://www.kafferaven.se/collections/all-coffee"]

    def __init__(self) -> None:
        self.base_url = "https://www.kafferaven.se"

    def parse(self, response: scrapy.http.Response) -> scrapy.Request:
        scraped_dir = Path("scraped")
        if not scraped_dir.exists():
            scraped_dir.mkdir()
        page = response.url.split("/")[-2]
        filename = Path(scraped_dir, f"{self.name}-{page}.html")
        with open(filename, "wb") as fh:
            fh.write(response.body)

        coffee_product_urls = [
            f"{self.base_url}{u}"
            for u in response.xpath(
                '//a[@class="product-link js-product-link"]/@href'
            ).getall()
        ]

        for cpu in coffee_product_urls:
            self.logger.debug(f"Acquired {cpu}")
            yield scrapy.Request(cpu, callback=self.parse_cpu)

        next_page = response.xpath('//span[@class="next"]//a/@href').get()
        if next_page is not None:
            next_page = response.urljoin(next_page)
            yield scrapy.Request(next_page, callback=self.parse)

    def parse_cpu(self, response: scrapy.http.Response) -> CoffeeItem:
        coffee_name = response.url.split("/")[-1]
        file_name = f"{self.name}-{coffee_name}.html"
        raw_path = Path("scraped", file_name)
        with open(raw_path, "wb") as fh:
            fh.write(response.body)

        # This is sketchy.... but it works.
        coffee_data = response.xpath(
            '//div[@class="product-single__content-text rte"]//ul//li'
        ).getall()

        for cd in coffee_data:
            self.logger.debug(cd)

        coffee_item = CoffeeItem()
        coffee_item["name"] = self.parse_coffee_name(coffee_name)
        coffee_item["roaster"] = "Kafferäven"
        coffee_item["type"] = self.parse_type(coffee_name)
        coffee_item["url"] = response.url
        coffee_item["origin"] = self.parse_coffee_origin(coffee_name, coffee_data)
        coffee_item["altitude"] = self.parse_coffee_data(coffee_data, "ALTITUDE")
        coffee_item["img"] = self.parse_coffee_img(response)

        return coffee_item

    def parse_coffee_name(self, coffee_name: str) -> str:
        """Remove hyphens and titelize the coffee name"""
        return coffee_name.replace("-", " ").title()

    def parse_type(self, coffee_name: str) -> str:
        """If Espresso is in the name, go with it, else assume Filter."""
        return "Espresso" if "espresso" in coffee_name.lower() else "Filter"

    def parse_coffee_origin(
        self, coffee_name: str, coffee_data: List[str]
    ) -> List[str]:
        """Attempt to extract the origin from the coffee name or description."""

        self.logger.debug("Attempting to fetch Country from 'Country' tag")
        if country_tag := self.parse_coffee_data(coffee_data, "COUNTRY"):
            if country := extract_country(country_tag[0]):
                return country

        self.logger.debug(
            f"Attempting to extract origin from coffee name: {coffee_name}"
        )
        if country_name := extract_country(coffee_name):
            return country_name

        self.logger.debug(
            "Could not find a country in coffee name, trying description:"
        )
        for row in coffee_data:
            if any(c.isalpha() for c in row):
                self.logger.debug(f"Searching in: {row}")
                if country_description := extract_country(row):
                    return country_description

        self.logger.debug("Unable to find a country.")
        return []

    def parse_coffee_data(self, coffee_data: List[str], property: str) -> List[str]:
        self.logger.debug(f"Looking for: {property}")
        self.logger.debug(f"Coffee data: {coffee_data}")
        for cd in coffee_data:
            if property in cd:
                return [Selector(text=cd).xpath("//li/text()").getall()[-1].strip()]
        return []

    def parse_coffee_img(self, response: scrapy.http.Response) -> str:
        resp: str = response.xpath(
            '//meta[@property="og:image:secure_url"]/@content'
        ).get()
        return resp
