import { Injectable, Logger } from "@nestjs/common"; import { PrismaService } from "../../database/prisma.service"; import { MatchAnalysisService, AnalysisResult, } from "../../services/match-analysis.service"; @Injectable() export class AnalysisService { private readonly logger = new Logger(AnalysisService.name); constructor( private readonly prisma: PrismaService, private readonly matchAnalysisService: MatchAnalysisService, ) {} /** * Analyze multiple matches (coupon) */ async analyzeCoupon(matchIds: string[], userId: string): Promise { this.logger.log(`Analyzing ${matchIds.length} matches for coupon`); const results: AnalysisResult[] = []; for (const matchId of matchIds) { try { // Get match from DB const match = await this.prisma.match.findFirst({ where: { OR: [{ id: matchId }], }, include: { league: true, homeTeam: true, awayTeam: true, }, }); // Try live match if not found const liveMatch = !match ? await this.prisma.liveMatch.findUnique({ where: { id: matchId }, }) : null; const targetMatch = match || liveMatch; if (!targetMatch) { this.logger.warn(`Match not found: ${matchId}`); continue; } // Build URL for analysis const sport = (targetMatch as any).sport || "football"; const slug = (targetMatch as any).matchSlug || matchId; const url = `https://www.mackolik.com/${sport === "basketball" ? "basketbol/mac" : "mac"}/${slug}/${matchId}`; // Run analysis const result = await this.matchAnalysisService.analyzeMatch( url, userId, ); results.push(result); } catch (err: any) { this.logger.warn(`Analysis failed for ${matchId}: ${err.message}`); } } if (results.length === 0) { return null; } // Combine results into coupon format return { totalMatches: matchIds.length, analyzedMatches: results.length, matches: results.map((r) => ({ matchDetails: r.matchDetails, predictions: r.aiAnalysis?.predictions || [], recommendedBets: r.aiAnalysis?.recommendedBets || [], confidence: r.aiAnalysis?.confidenceScore || 0, })), generatedAt: new Date().toISOString(), }; } /** * Check user usage limit */ async checkUsageLimit( userId: string, isCoupon: boolean, matchCount: number, ): Promise { const usageLimit = await this.prisma.usageLimit.findUnique({ where: { userId }, }); if (!usageLimit) { // Create default limit await this.prisma.usageLimit.create({ data: { userId, analysisCount: 0, couponCount: 0, lastResetDate: new Date(), }, }); return true; } // Check limits (default: 10 analyses, 3 coupons per day) const user = await this.prisma.user.findUnique({ where: { id: userId } }); const isPremium = user?.subscriptionStatus === "active"; const maxAnalyses = isPremium ? 50 : 10; const maxCoupons = isPremium ? 10 : 3; if (isCoupon) { return usageLimit.couponCount < maxCoupons; } return usageLimit.analysisCount + matchCount <= maxAnalyses; } /** * Record usage */ async recordUsage(userId: string, isCoupon: boolean): Promise { if (isCoupon) { await this.prisma.usageLimit.update({ where: { userId }, data: { couponCount: { increment: 1 } }, }); } else { await this.prisma.usageLimit.update({ where: { userId }, data: { analysisCount: { increment: 1 } }, }); } } /** * Get user analysis history */ async getAnalysisHistory(userId: string, limit: number = 20) { return this.prisma.analysis.findMany({ where: { userId }, orderBy: { createdAt: "desc" }, take: limit, }); } }