"""
AI-Powered Product Recommendation System
Uses collaborative filtering and content-based recommendations
"""
import os
from django.conf import settings
from django.db import models
from products.models import Product
from orders.models import Order, OrderItem


class ProductRecommender:
    """AI Product Recommendation Engine"""
    
    def __init__(self):
        self.products = Product.objects.filter(is_active=True)
    
    def get_recommendations_for_user(self, user, limit=10):
        """
        Get personalized recommendations based on user's purchase history
        """
        # Get user's past orders
        user_orders = Order.objects.filter(user=user, is_paid=True)
        
        if not user_orders.exists():
            # Return trending products for new users
            return self.get_trending_products(limit)
        
        # Get previously purchased products
        purchased_products = OrderItem.objects.filter(
            order__in=user_orders
        ).values_list('product_id', flat=True).distinct()
        
        # Get products similar to purchased ones
        similar_products = []
        for product_id in purchased_products[:5]:  # Limit to last 5
            try:
                product = Product.objects.get(id=product_id, is_active=True)
                similar = self.get_similar_products(product, limit=5)
                similar_products.extend(similar)
            except Product.DoesNotExist:
                continue
        
        # Remove duplicates and previously purchased
        recommendations = []
        seen = set(purchased_products)
        
        for product in similar_products:
            if product.id not in seen and len(recommendations) < limit:
                recommendations.append(product)
                seen.add(product.id)
        
        # Fill with trending if needed
        if len(recommendations) < limit:
            trending = self.get_trending_products(limit - len(recommendations))
            for product in trending:
                if product.id not in seen and len(recommendations) < limit:
                    recommendations.append(product)
        
        return recommendations
    
    def get_similar_products(self, product, limit=5):
        """
        Get products similar to the given product (content-based)
        Based on category, brand, and description similarity
        """
        # Same category products
        similar = Product.objects.filter(
            category=product.category,
            is_active=True
        ).exclude(id=product.id)
        
        # Prioritize same brand
        same_brand = similar.filter(brand=product.brand)
        
        # Combine results
        results = list(same_brand[:limit//2]) + list(similar.exclude(brand=product.brand)[:limit//2])
        
        return results[:limit]
    
    def get_trending_products(self, limit=10):
        """
        Get trending products based on recent sales and views
        """
        return Product.objects.filter(
            is_active=True
        ).order_by('-sales_count', '-views_count')[:limit]
    
    def get_frequently_bought_together(self, product, limit=5):
        """
        Find products frequently bought together with the given product
        """
        # Get orders containing this product
        orders_with_product = OrderItem.objects.filter(
            product=product
        ).values_list('order_id', flat=True)
        
        # Get other products from those orders
        other_products = OrderItem.objects.filter(
            order_id__in=orders_with_product
        ).exclude(
            product=product
        ).values('product').annotate(
            count=models.Count('product')
        ).order_by('-count')[:limit]
        
        # Get product objects
        product_ids = [item['product'] for item in other_products]
        return Product.objects.filter(id__in=product_ids, is_active=True)
    
    def get_best_sellers_in_category(self, category, limit=10):
        """
        Get best-selling products in a specific category
        """
        return Product.objects.filter(
            category=category,
            is_active=True
        ).order_by('-sales_count')[:limit]
    
    def predict_user_interest(self, user, product):
        """
        Predict if a user might be interested in a product (0-1 score)
        """
        score = 0.5  # Base score
        
        # Check user's purchase history
        user_categories = OrderItem.objects.filter(
            order__user=user,
            order__is_paid=True
        ).values_list('product__category', flat=True).distinct()
        
        if product.category_id in user_categories:
            score += 0.3
        
        # Check if product is trending
        if product.is_best_seller:
            score += 0.1
        
        # Check rating
        if product.average_rating >= 4:
            score += 0.1
        
        return min(score, 1.0)


# Utility function
def get_recommendations(user=None, product=None, recommendation_type='personalized', limit=10):
    """
    Unified recommendation function
    
    Args:
        user: User instance
        product: Product instance
        recommendation_type: 'personalized', 'similar', 'trending', 'frequently_bought'
        limit: Number of recommendations
    
    Returns:
        QuerySet of recommended products
    """
    recommender = ProductRecommender()
    
    if recommendation_type == 'personalized' and user:
        return recommender.get_recommendations_for_user(user, limit)
    elif recommendation_type == 'similar' and product:
        return recommender.get_similar_products(product, limit)
    elif recommendation_type == 'frequently_bought' and product:
        return recommender.get_frequently_bought_together(product, limit)
    else:
        return recommender.get_trending_products(limit)
