from typing import Protocol

from zbt.domains.catalog.models import Product, ProductChangeLog, ProductVersion


class CatalogRepository(Protocol):
    def save_product(self, product: Product) -> None: ...

    def list_products(self) -> list[Product]: ...

    def list_versions(self, product_id: str) -> list[ProductVersion]: ...

    def save_version(self, version: ProductVersion) -> None: ...

    def delete_version(self, version_id: str) -> None: ...

    def save_change_log(self, log: ProductChangeLog) -> None: ...

    def list_change_logs(self, product_id: str) -> list[ProductChangeLog]: ...


class InMemoryCatalogRepository:
    def __init__(self) -> None:
        self._products: dict[str, Product] = {}
        self._versions: dict[str, list[ProductVersion]] = {}
        self._change_logs: list[ProductChangeLog] = []

    def save_product(self, product: Product) -> None:
        self._products[product.id] = product

    def save_version(self, version: ProductVersion) -> None:
        versions = self._versions.setdefault(version.product_id, [])
        for index, existing in enumerate(versions):
            if existing.id == version.id:
                versions[index] = version
                break
        else:
            versions.append(version)

    def list_products(self) -> list[Product]:
        return list(self._products.values())

    def list_versions(self, product_id: str) -> list[ProductVersion]:
        return list(self._versions.get(product_id, []))

    def delete_version(self, version_id: str) -> None:
        for product_id, versions in self._versions.items():
            self._versions[product_id] = [
                version for version in versions if version.id != version_id
            ]

    def save_change_log(self, log: ProductChangeLog) -> None:
        self._change_logs.append(log)

    def list_change_logs(self, product_id: str) -> list[ProductChangeLog]:
        return [log for log in self._change_logs if log.product_id == product_id]
