from pathlib import Path
from typing import List
import re

import scrapy

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


class GringoSpider(scrapy.Spider):  # type: ignore
    name = "gringo"
    start_urls = [
        "https://www.gringonordic.se/shop",
    ]

    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 = response.xpath(
            '//a[@data-hook="product-item-container"]/@href'
        ).getall()

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

    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)

        coffee_data = "\n".join(
            response.xpath('//pre[@data-hook="description"]/p/text()').getall()
        )

        self.logger.debug("DESCRIPTION")
        self.logger.debug(coffee_data)

        coffee_item = CoffeeItem()
        coffee_item["name"] = self.parse_coffee_name(coffee_name)
        coffee_item["roaster"] = "Gringo Nordic"
        coffee_item["type"] = self.parse_type(coffee_name)
        coffee_item["origin"] = self.parse_origin(coffee_data)
        coffee_item["altitude"] = self.parse_altitude(coffee_data)
        coffee_item["process"] = self.parse_process(coffee_data)
        coffee_item["url"] = response.url
        coffee_item["img"] = self.parse_coffee_img(response)

        return coffee_item

    def parse_coffee_name(self, coffee_name: str) -> str:
        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_origin(self, description: str) -> List[str]:
        self.logger.debug("Attempting to fetch countries using tags")
        patterns = ["Plats:", "Land:"]
        for pattern in patterns:
            matches = re.search(f"(?<={pattern})(.*)", description, re.MULTILINE)
            if matches:
                match = matches.group(0).split(",")[-1].strip()
                self.logger.debug(f"Found a match for the tag {pattern}: {match}")
                return extract_country(match)

        return []

    def parse_altitude(self, description: str) -> List[str]:
        matches = re.search(r"(?<=Altitud: )(.*)", description, re.MULTILINE)
        if matches:
            return [matches.group(0).replace("meter", "").strip()]
        return []

    def parse_process(self, description: str) -> List[str]:
        matches = re.search(r"(?<=Bearbetning:)(.*)", description, re.MULTILINE)
        if matches:
            return [matches.group(0).strip()]
        return []

    def parse_coffee_img(self, response: scrapy.http.Response) -> str:
        coffee_img_url: str = response.xpath(
            '//meta[@property="og:image"]/@content'
        ).get()
        # url is on the form https://<stuff>.<ext>/<formatting stuff>.<ext>
        if ".png" in coffee_img_url:
            ext = ".png"
        if ".jpg" in coffee_img_url:
            ext = ".jpg"
        first_ext = coffee_img_url.find(ext)
        return coffee_img_url[:first_ext] + ext
