"""Product service for product listing and discovery operations.

This service handles business logic for product queries, following
the service layer pattern (ADR-006). It is framework-agnostic and can
be used from MCP tools, REST APIs, CLI, or webhooks.

STORY-023d: Simplified to product-only operations (list_tests moved to TestService).

Responsibilities:
- Product listing and filtering (search, product_type)
- Database query orchestration (local SQLite cache)
- Domain exception raising

Does NOT handle:
- MCP protocol formatting
- User-facing error messages
- HTTP transport concerns
- Test operations (now handled by TestService)
"""

import logging
from typing import Any

from testio_mcp.services.base_service import BaseService

logger = logging.getLogger(__name__)


class ProductService(BaseService):
    """Business logic for product operations.

    Uses PersistentCache for SQLite queries (STORY-023c).

    Example:
        ```python
        from testio_mcp.database import PersistentCache

        service = ProductService(client=client, cache=cache)
        products = await service.list_products(search="studio")
        ```
    """

    def __init__(
        self,
        client: Any,
        cache: Any,
    ) -> None:
        """Initialize service with API client and cache.

        Args:
            client: TestIO API client
            cache: Persistent cache for database queries
        """
        super().__init__(client)
        self.cache = cache

    async def list_products(
        self,
        search: str | None = None,
        product_type: str | list[str] | None = None,
    ) -> dict[str, Any]:
        """List all products accessible to the user with optional filtering.

        Implements cache-raw pattern (ADR-004):
        1. Cache full API response (no filter in cache key)
        2. Filter in-memory on every call (fast, <1ms)
        3. Result: 95%+ cache hit rate regardless of filter combinations

        Args:
            search: Optional search term (filters by name/description)
            product_type: Optional filter by product type(s) - single string or list

        Returns:
            Dictionary with product list and metadata

        Raises:
            TestIOAPIError: If API returns error response

        Example:
            >>> products = await service.list_products(search="studio")
            >>> print(products["total_count"])
            2
            >>> print(products["products"][0]["name"])
            'Studio Pro'
        """

        # Fetch products directly from API (STORY-023c: simplified, no caching)
        # Note: Products could be queried from SQLite in future optimization
        raw_response = await self.client.get("products")

        # Filter in-memory (fast, <1ms)
        all_products = raw_response.get("products", [])
        filtered_products = self._apply_filters(all_products, search, product_type)

        # Build result with filter metadata
        return {
            "total_count": len(filtered_products),
            "filters_applied": {
                "search": search,
                "product_type": product_type,
            },
            "products": filtered_products,
        }

    def _apply_filters(
        self,
        products: list[dict[str, Any]],
        search: str | None,
        product_type: str | list[str] | None,
    ) -> list[dict[str, Any]]:
        """Apply search and type filters to products.

        This is a private helper method that filters raw product data:
        - Search: Case-insensitive substring match on name or description
        - Product type: Match on type field (single value or list)

        Args:
            products: List of product dictionaries from API
            search: Optional search term
            product_type: Optional product type filter(s) - single string or list

        Returns:
            Filtered list of products

        Example:
            >>> products = [
            ...     {"id": "1", "name": "Studio Pro", "type": "website"},
            ...     {"id": "2", "name": "Mobile App", "type": "mobile"}
            ... ]
            >>> filtered = service._apply_filters(products, "studio", None)
            >>> len(filtered)
            1
            >>> filtered[0]["name"]
            'Studio Pro'
        """
        filtered = products

        # Filter by search term (case-insensitive, name or description)
        if search:
            search_lower = search.lower()
            filtered = [
                p
                for p in filtered
                if search_lower in (p.get("name") or "").lower()
                or search_lower in (p.get("description") or "").lower()
            ]

        # Filter by product type(s)
        if product_type:
            # Normalize to list for consistent filtering
            types = [product_type] if isinstance(product_type, str) else product_type
            filtered = [p for p in filtered if p.get("type") in types]

        return filtered
