"""Product and content recommendation models.

TODO: Implement recommendation engines for commerce use cases:
    - Collaborative filtering (user-item interactions)
    - Content-based filtering (product attributes)
    - Hybrid approaches (combine both signals)
    - "Frequently bought together" association rules

Planned backends:
    - implicit: Fast collaborative filtering (ALS, BPR) — good for implicit feedback
    - lightfm: Hybrid model that combines collaborative + content features

Usage (planned):
    from platoon.learning.providers import get_provider
    rec = get_provider("recommendations")

    # Train on order history
    rec.fit(orders, product_features=products)

    # Get recommendations for a customer
    recs = rec.recommend(customer_id="CUST-001", n=10)
    print(recs.items)  # [{"product_id": "PROD-42", "score": 0.93}, ...]

    # Find similar products
    similar = rec.similar_items(product_id="PROD-42", n=5)

CLI (planned):
    platoon recommend --orders data/samples/orders.csv --customer CUST-001
    platoon recommend --orders data/samples/orders.csv --product PROD-1001 --similar
    platoon recommend --orders data/samples/orders.csv --popular --top 10
"""

from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional

from platoon.learning.providers import ModelProvider, register_provider


# ---------------------------------------------------------------------------
# Result types
# ---------------------------------------------------------------------------


@dataclass
class RecommendationResult:
    """Output of a recommendation query."""

    items: List[Dict[str, Any]]  # [{product_id, score, title?, reason?}]
    customer_id: Optional[str] = None
    method: str = ""
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class SimilarItemsResult:
    """Output of a similar-items query."""

    source_item: str
    items: List[Dict[str, Any]]  # [{product_id, score, title?}]
    method: str = ""


# ---------------------------------------------------------------------------
# Provider stubs
# ---------------------------------------------------------------------------


@register_provider
class ImplicitProvider(ModelProvider):
    """Collaborative filtering via the implicit library (ALS, BPR).

    TODO: Implement fit/recommend/similar_items using implicit.als.AlternatingLeastSquares
    Best for: pure implicit feedback (views, purchases, clicks).
    Requires: implicit
    """

    name = "implicit_recommendations"
    domain = "recommendations"
    backend = "implicit"

    @classmethod
    def is_available(cls) -> bool:
        try:
            import implicit  # noqa: F401
            return True
        except ImportError:
            return False

    def fit(self, orders: List[Dict], **kwargs) -> None:
        """Train the model on order/interaction data."""
        raise NotImplementedError("implicit provider not yet implemented")

    def recommend(self, customer_id: str, n: int = 10, **kwargs) -> RecommendationResult:
        """Get top-N product recommendations for a customer."""
        raise NotImplementedError("implicit provider not yet implemented")

    def similar_items(self, product_id: str, n: int = 10, **kwargs) -> SimilarItemsResult:
        """Find N most similar products."""
        raise NotImplementedError("implicit provider not yet implemented")


@register_provider
class LightFMProvider(ModelProvider):
    """Hybrid recommendation model via LightFM.

    TODO: Implement fit/recommend using lightfm.LightFM
    Best for: combining collaborative signals with product/user features.
    Requires: lightfm
    """

    name = "lightfm_recommendations"
    domain = "recommendations"
    backend = "lightfm"

    @classmethod
    def is_available(cls) -> bool:
        try:
            import lightfm  # noqa: F401
            return True
        except ImportError:
            return False

    def fit(self, orders: List[Dict], product_features: Optional[List[Dict]] = None, **kwargs) -> None:
        """Train the hybrid model on orders + optional product features."""
        raise NotImplementedError("lightfm provider not yet implemented")

    def recommend(self, customer_id: str, n: int = 10, **kwargs) -> RecommendationResult:
        """Get top-N product recommendations for a customer."""
        raise NotImplementedError("lightfm provider not yet implemented")

    def similar_items(self, product_id: str, n: int = 10, **kwargs) -> SimilarItemsResult:
        """Find N most similar products using learned embeddings."""
        raise NotImplementedError("lightfm provider not yet implemented")
