<?php

namespace App\Services;

use App\Models\Item;
use App\Models\User;
use App\Models\UserPreference;
use App\Models\UserInteraction;
use App\Models\Category;
use Illuminate\Support\Facades\DB;

class RecommendationService
{
    public function getPersonalizedItems($user = null, $limit = 12)
    {
        if (!$user) {
            return $this->getFallbackItems($limit);
        }

        $preferences = $user->preferences;
        if (!$preferences || !$preferences->onboarding_completed) {
            return $this->getPopularItems($limit);
        }

        // Get user's behavioral interests
        $categoryInterests = UserInteraction::getUserCategoryInterests($user->id);
        $avgPriceInterest = UserInteraction::getUserPriceInterests($user->id);

        // Build personalized query
        $query = Item::with(['user', 'category', 'primaryPhoto'])
            ->whereIn('status', ['active', 'sale_pending'])
            ->whereIn('listing_type', ['sale', 'trade'])
            ->whereHas('user', function($q) {
                $q->where('is_active', true);
            });

        // Exclude flagged items unless user is admin
        if (!$user->is_admin) {
            $query->where('status', '!=', 'flagged');
        }

        // Exclude user's own items
        $query->where('user_id', '!=', $user->id);

        // Apply preference-based scoring
        $query->selectRaw('items.*, (
            CASE 
                WHEN category_id IN (' . implode(',', array_keys($categoryInterests)) . ') THEN 3
                WHEN category_id IN (' . implode(',', $preferences->preferred_categories ?? []) . ') THEN 2
                ELSE 1
            END +
            CASE 
                WHEN listing_type IN ("' . implode('","', $preferences->preferred_listing_types ?? ['sale', 'trade']) . '") THEN 1
                ELSE 0
            END +
            CASE 
                WHEN condition IN ("' . implode('","', $preferences->preferred_conditions ?? ['excellent', 'good', 'fair']) . '") THEN 1
                ELSE 0
            END +
            CASE 
                WHEN price IS NULL THEN 1
                WHEN price BETWEEN 0 AND 1000 THEN 1
                ELSE 0.5
            END
        ) as relevance_score');

        $items = $query->orderByDesc('relevance_score')
            ->orderBy(DB::raw('RAND()'))
            ->limit($limit)
            ->get();

        // If we don't have enough personalized items, fill with popular ones
        if ($items->count() < $limit) {
            $additional = $this->getPopularItems($limit - $items->count(), $items->pluck('id')->toArray());
            $items = $items->merge($additional);
        }

        return $items;
    }

    public function getPopularItems($limit = 12, $excludeIds = [])
    {
        return Item::with(['user', 'category', 'primaryPhoto'])
            ->whereIn('status', ['active', 'sale_pending'])
            ->whereIn('listing_type', ['sale', 'trade'])
            ->whereNotIn('id', $excludeIds)
            ->whereHas('user', function($q) {
                $q->where('is_active', true);
            })
            ->where('status', '!=', 'flagged')
            ->withCount('watchlists as watchers_count')
            ->orderByDesc('views')
            ->orderByDesc('watchers_count')
            ->orderBy(DB::raw('RAND()'))
            ->limit($limit)
            ->get();
    }

    public function getFallbackItems($limit = 12)
    {
        return Item::with(['user', 'category', 'primaryPhoto'])
            ->whereIn('status', ['active', 'sale_pending'])
            ->whereIn('listing_type', ['sale', 'trade'])
            ->whereHas('user', function($q) {
                $q->where('is_active', true);
            })
            ->where('status', '!=', 'flagged')
            ->latest()
            ->limit($limit)
            ->get();
    }

    public function getSimilarItems($item, $limit = 4)
    {
        return Item::with(['primaryPhoto'])
            ->where('category_id', $item->category_id)
            ->where('id', '!=', $item->id)
            ->whereIn('status', ['active', 'sale_pending'])
            ->whereIn('listing_type', ['sale', 'trade'])
            ->whereHas('user', function($q) {
                $q->where('is_active', true);
            })
            ->where('status', '!=', 'flagged')
            ->when($item->price, function($query) use ($item) {
                // Show items in similar price range
                $priceRange = $item->price * 0.3; // 30% variance
                return $query->whereBetween('price', [
                    $item->price - $priceRange,
                    $item->price + $priceRange
                ]);
            })
            ->orderBy(DB::raw('RAND()'))
            ->limit($limit)
            ->get();
    }

    public function getCategoryRecommendations($categoryId, $user = null, $limit = 8)
    {
        $query = Item::with(['user', 'category', 'primaryPhoto'])
            ->where('category_id', $categoryId)
            ->whereIn('status', ['active', 'sale_pending'])
            ->whereIn('listing_type', ['sale', 'trade'])
            ->whereHas('user', function($q) {
                $q->where('is_active', true);
            })
            ->where('status', '!=', 'flagged');

        if ($user) {
            $query->where('user_id', '!=', $user->id);
        }

        return $query->withCount('watchlists as watchers_count')
            ->orderByDesc('watchers_count')
            ->orderByDesc('views')
            ->limit($limit)
            ->get();
    }

    public function updateUserPreferencesFromBehavior($user)
    {
        if (!$user->preferences) {
            return;
        }

        $categoryInterests = UserInteraction::getUserCategoryInterests($user->id, 7); // Last 7 days
        
        if (count($categoryInterests) > 0) {
            // Get top 3 categories from recent behavior
            $topCategories = array_slice(array_keys($categoryInterests), 0, 3);
            
            // Merge with existing preferences
            $existingCategories = $user->preferences->preferred_categories ?? [];
            $mergedCategories = array_unique(array_merge($existingCategories, $topCategories));
            
            $user->preferences->update([
                'preferred_categories' => $mergedCategories
            ]);
        }
    }
}