import re
from random import randrange

from gdshoplib.apps.products.description import ProductDescription
from gdshoplib.apps.products.media import ProductMedia
from gdshoplib.apps.products.price import Price
from gdshoplib.core.settings import ProductSettings
from gdshoplib.packages.barcode_pack import Barcode
from gdshoplib.services.notion.database import Database
from gdshoplib.services.notion.page import Page


class Product(Page):
    SETTINGS = ProductSettings()

    def __init__(self, *args, **kwargs):
        self._images = None
        self._videos = None
        self._price = None
        self._description = None
        self._kit = None
        self._badges = None

        super(Product, self).__init__(*args, **kwargs)

    @classmethod
    def get(cls, sku):
        page = [
            page
            for page in Database(cls.SETTINGS.PRODUCT_DB).pages(
                params={
                    "filter": {
                        "property": "Наш SKU",
                        "rich_text": {
                            "equals": sku,
                        },
                    }
                }
            )
        ]
        if not page:
            return
        if len(page) > 1:
            raise SKUDuplicate
        page = page[0]

        return cls(page["id"], notion=page.notion, parent=page.parent)

    @classmethod
    def query(cls, filter=None, params=None, notion=None):
        for page in Database(cls.SETTINGS.PRODUCT_DB, notion=notion).pages(
            filter=filter, params=params
        ):
            yield cls(page["id"], notion=page.notion, parent=page.parent)

    @property
    def barcode(self):
        if self.barcode_code_field:
            return Barcode(self.barcode_code_field)
        if self.barcode_image_field:
            return Barcode.read(self.barcode_image_field.image)

    @property
    def media(self):
        return [*self.images, *self.videos]

    @property
    def videos(self):
        if not self._videos:
            self._videos = list(
                ProductMedia(block.id, notion=self.notion, parent=self)
                for block in self.blocks(filter={"type": "video"})
            )
        return self._videos

    @property
    def images(self):
        if not self._images:
            self._images = list(
                ProductMedia(block.id, notion=self.notion, parent=self)
                for block in self.blocks(filter={"type": "image"})
            )
        return self._images

    @property
    def price(self):
        if not self._price:
            self._price = Price(self)
        return self._price

    @property
    def description(self):
        if not self._description:
            self._description = ProductDescription(self)
        return self._description

    @staticmethod
    def split(source):
        result = []
        if not source:
            return []

        for tag in source.split("/"):
            result.append(tag.strip())

        return result

    @property
    def tags(self):
        result = []
        for tag in self.split(self.tags_field):
            result.append(re.sub(r"[\W\s]", "", tag).lower())
        return result

    @property
    def specifications(self):
        result = []
        for spec in self.split(self.specifications_field):
            result.append(spec.capitalize())
        return result

    @property
    def notes(self):
        result = []
        for spec in self.split(self.notes_field):
            result.append(spec.capitalize())
        return result

    @property
    def kit(self):
        if not self.kit_field:
            return

        if not self._kit:
            self._kit = []
            for page in self.kit_field:
                if self.id != page.id:
                    self._kit.append(
                        Product(page.id, notion=self.notion, parent=self.parent)
                    )
        return self._kit

    @property
    def platforms(self):
        # Получить платформы из фида и вернуть объект класса <Platform>
        ...

    @property
    def badges(self):
        if not self.badge_field:
            return

        if not self._badges:
            self._badges = []
            for page in self.badge_field:
                if self.id != page.id:
                    self._badges.append(
                        Page(page.id, notion=self.notion, parent=self.parent)
                    )
        return self._badges

    def available(self):
        return bool(
            self.quantity
            and self.status_publication == "Публикация"
            and self.status_description == "Готово"
        )

    def generate_sku(self):
        # Сгенерировать SKU на основе продукта
        # Категория.Бренд.Цена_покупки.месяц_добавления.год_добавления.случайные_4_числа

        sku = (
            f"{self.brand.title.upper() if self.brand else ''}"
            f"{int(self.price.eur)}"
            f"{randrange(1111, 9999)}"
        )

        return re.sub(r"\W", "", sku)

    def __str__(self) -> str:
        return f"{self.__class__}: {self.sku}"

    def __repr__(self) -> str:
        return f"{self.__class__}: {self.sku}"

    def warm(self):
        self.price.now
        self.kit
        self.notes
        self.specifications
        self.tags
        self.media
        self.description
        self.brand.title
        self.description.warm_description_blocks()


class SKUDuplicate(Exception):
    # Если найден товар с одинаковым SKU
    ...
