"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AIRecommendationsService = void 0;
const database_1 = __importDefault(require("../config/database"));
const ai_service_1 = require("./ai.service");
class AIRecommendationsService {
    /**
     * Semantic Vector & Attribute-Based Similar Books Recommendation
     */
    static async getSimilarBooks(bookId, limit = 6) {
        const targetBook = await database_1.default.book.findUnique({
            where: { id: bookId },
            include: {
                bookAuthors: { include: { author: true } },
                bookCategories: { include: { category: true } },
            },
        });
        if (!targetBook) {
            throw new Error('Target book not found');
        }
        const authorIds = targetBook.bookAuthors.map((a) => a.authorId);
        const categoryIds = targetBook.bookCategories.map((c) => c.categoryId);
        // 1. Fetch candidate books in related categories or by related authors
        const candidates = await database_1.default.book.findMany({
            where: {
                id: { not: bookId },
                isActive: true,
            },
            include: {
                bookAuthors: { include: { author: true } },
                bookCategories: { include: { category: true } },
                images: { where: { isPrimary: true }, take: 1 },
                variants: { where: { isActive: true } },
            },
            take: 50,
            orderBy: { ratingAverage: 'desc' },
        });
        if (candidates.length === 0)
            return [];
        // 2. Generate target embedding
        const targetText = `${targetBook.title} ${targetBook.description || ''} ${targetBook.bookCategories.map((c) => c.category.name).join(' ')} ${targetBook.bookAuthors.map((a) => a.author.name).join(' ')}`;
        const targetVector = await ai_service_1.AIService.generateEmbedding(targetText);
        // 3. Compute similarity scores
        const scoredCandidates = await Promise.all(candidates.map(async (candidate) => {
            const candidateText = `${candidate.title} ${candidate.description || ''} ${candidate.bookCategories.map((c) => c.category.name).join(' ')} ${candidate.bookAuthors.map((a) => a.author.name).join(' ')}`;
            const candidateVector = await ai_service_1.AIService.generateEmbedding(candidateText);
            const semanticScore = ai_service_1.AIService.cosineSimilarity(targetVector, candidateVector);
            // Boost for shared author or category
            const sharedAuthor = candidate.bookAuthors.some((a) => authorIds.includes(a.authorId)) ? 0.35 : 0;
            const sharedCategory = candidate.bookCategories.some((c) => categoryIds.includes(c.categoryId)) ? 0.25 : 0;
            const totalScore = semanticScore * 0.4 + sharedAuthor + sharedCategory;
            return {
                book: candidate,
                score: totalScore,
                semanticScore: Math.round(semanticScore * 100),
            };
        }));
        // Sort by highest score
        scoredCandidates.sort((a, b) => b.score - a.score);
        return scoredCandidates.slice(0, limit).map((item) => ({
            id: item.book.id,
            title: item.book.title,
            slug: item.book.slug,
            price: Number(item.book.price),
            discountPrice: item.book.discountPrice ? Number(item.book.discountPrice) : null,
            coverImage: item.book.coverImage || item.book.images[0]?.url || null,
            authorName: item.book.bookAuthors[0]?.author.name || 'Indian Author',
            categoryName: item.book.bookCategories[0]?.category.name || 'General',
            format: item.book.format,
            ratingAverage: Number(item.book.ratingAverage),
            similarityScore: item.semanticScore,
            recommendationReason: `Recommended based on thematic synergy with “${targetBook.title.slice(0, 30)}...”`,
        }));
    }
    /**
     * Personalized User Recommendations based on Cart, Wishlist, and Order history
     */
    static async getPersonalizedRecommendations(userId, limit = 8) {
        // 1. Fetch user's interactions
        const [cart, wishlist, orders] = await Promise.all([
            database_1.default.shoppingCart.findUnique({
                where: { userId },
                include: { items: { include: { book: { include: { bookCategories: { include: { category: true } } } } } } },
            }),
            database_1.default.wishlist.findUnique({
                where: { userId },
                include: { items: { include: { book: { include: { bookCategories: { include: { category: true } } } } } } },
            }),
            database_1.default.order.findMany({
                where: { userId },
                include: { items: { include: { book: { include: { bookCategories: { include: { category: true } } } } } } },
                take: 5,
            }),
        ]);
        const userBookIds = new Set();
        const interactedSubjects = [];
        cart?.items.forEach((i) => {
            userBookIds.add(i.bookId);
            i.book.bookCategories.forEach((c) => interactedSubjects.push(c.category.name));
        });
        wishlist?.items.forEach((i) => {
            userBookIds.add(i.bookId);
            i.book.bookCategories.forEach((c) => interactedSubjects.push(c.category.name));
        });
        orders.forEach((o) => o.items.forEach((i) => {
            userBookIds.add(i.bookId);
            i.book.bookCategories.forEach((c) => interactedSubjects.push(c.category.name));
        }));
        // If new user with no history, return top curated trending books
        if (userBookIds.size === 0) {
            return this.getTrendingAIRecommendations(limit);
        }
        // 2. Fetch catalog books excluding already interacted books
        const availableBooks = await database_1.default.book.findMany({
            where: {
                id: { notIn: Array.from(userBookIds) },
                isActive: true,
            },
            include: {
                bookAuthors: { include: { author: true } },
                bookCategories: { include: { category: true } },
                images: { where: { isPrimary: true }, take: 1 },
            },
            take: 40,
            orderBy: [{ isFeatured: 'desc' }, { ratingAverage: 'desc' }],
        });
        const userProfileText = interactedSubjects.join(' ') || 'Classical Indian Philosophy Sanskrit Literature';
        const profileVector = await ai_service_1.AIService.generateEmbedding(userProfileText);
        const scored = await Promise.all(availableBooks.map(async (book) => {
            const text = `${book.title} ${book.description || ''} ${book.bookCategories.map((c) => c.category.name).join(' ')}`;
            const vector = await ai_service_1.AIService.generateEmbedding(text);
            const score = ai_service_1.AIService.cosineSimilarity(profileVector, vector);
            return { book, score };
        }));
        scored.sort((a, b) => b.score - a.score);
        return scored.slice(0, limit).map((item) => ({
            id: item.book.id,
            title: item.book.title,
            slug: item.book.slug,
            price: Number(item.book.price),
            discountPrice: item.book.discountPrice ? Number(item.book.discountPrice) : null,
            coverImage: item.book.coverImage || item.book.images[0]?.url || null,
            authorName: item.book.bookAuthors[0]?.author.name || 'Indian Author',
            categoryName: item.book.bookCategories[0]?.category.name || 'General',
            format: item.book.format,
            ratingAverage: Number(item.book.ratingAverage),
            recommendationReason: 'Personalized for your reading tastes in classical Indian literature',
        }));
    }
    /**
     * Trending AI Curated Recommendations
     */
    static async getTrendingAIRecommendations(limit = 8) {
        const books = await database_1.default.book.findMany({
            where: { isActive: true },
            include: {
                bookAuthors: { include: { author: true } },
                bookCategories: { include: { category: true } },
                images: { where: { isPrimary: true }, take: 1 },
            },
            take: limit,
            orderBy: [{ isBestseller: 'desc' }, { ratingAverage: 'desc' }, { createdAt: 'desc' }],
        });
        return books.map((book) => ({
            id: book.id,
            title: book.title,
            slug: book.slug,
            price: Number(book.price),
            discountPrice: book.discountPrice ? Number(book.discountPrice) : null,
            coverImage: book.coverImage || book.images[0]?.url || null,
            authorName: book.bookAuthors[0]?.author.name || 'Indian Author',
            categoryName: book.bookCategories[0]?.category.name || 'General',
            format: book.format,
            ratingAverage: Number(book.ratingAverage),
            recommendationReason: 'Trending Bestseller in Indian Literature & Scriptures',
        }));
    }
}
exports.AIRecommendationsService = AIRecommendationsService;
//# sourceMappingURL=ai-recommendations.service.js.map