<?php

namespace App\Services;

use App\Models\SrsReview;
use App\Models\User;
use App\Models\Vocabulary;
use Carbon\Carbon;

class SrsService
{
    /**
     * Process a review using SuperMemo-2 Algorithm.
     * 
     * @param User $user
     * @param Vocabulary $vocab
     * @param int $grade (1=Again, 2=Hard, 3=Good, 4=Easy)
     *        Mapped to SM-2 Quality (q):
     *        1 (Again) -> q=1
     *        2 (Hard)  -> q=3
     *        3 (Good)  -> q=4
     *        4 (Easy)  -> q=5
     */
    public function processReview(User $user, Vocabulary $vocab, int $grade)
    {
        // Map UI Grade to SM-2 Quality
        // Mapping: 1->1, 2->3, 3->4, 4->5
        $qualityMap = [1 => 1, 2 => 3, 3 => 4, 4 => 5];
        $q = $qualityMap[$grade] ?? 3;

        // Find existing review or create new
        $review = SrsReview::firstOrNew([
            'user_id' => $user->id,
            'vocabulary_id' => $vocab->id
        ]);

        if (!$review->exists) {
            // Defaults
            $review->ease_factor = 2.5;
            $review->interval = 0;
            $review->repetitions = 0;
            $review->status = 'new';
        }

        // SM-2 Algorithm Implementation
        if ($q >= 3) {
            // Correct response
            if ($review->repetitions == 0) {
                $review->interval = 1;
            } elseif ($review->repetitions == 1) {
                $review->interval = 6;
            } else {
                $review->interval = round($review->interval * $review->ease_factor);
            }
            $review->repetitions++;
            $review->status = $review->interval > 21 ? 'graduated' : 'review';
        } else {
            // Incorrect response
            $review->repetitions = 0;
            $review->interval = 1;
            $review->status = 'learning';
        }

        // Update Ease Factor
        // EF' = EF + (0.1 - (5 - q) * (0.08 + (5 - q) * 0.02))
        $review->ease_factor = $review->ease_factor + (0.1 - (5 - $q) * (0.08 + (5 - $q) * 0.02));
        if ($review->ease_factor < 1.3) {
            $review->ease_factor = 1.3;
        }

        $review->last_review_at = Carbon::now();
        $review->next_review_at = Carbon::now()->addDays($review->interval);
        
        $review->save();

        // Track Activity (XP and Streak)
        $this->trackActivity($user, $grade);

        return $review;
    }

    public function trackActivity(User $user, int $grade)
    {
        $today = Carbon::today();
        $lastActivity = $user->last_activity_at ? Carbon::parse($user->last_activity_at)->startOfDay() : null;

        // Award XP (Easy gives slightly more?)
        // Let's just do 5 XP per card for now.
        $user->xp_points += 5;

        if (!$lastActivity) {
            // First activity ever
            $user->current_streak = 1;
        } elseif ($today->isSameDay($lastActivity)) {
            // Already active today, do nothing to streak
        } elseif ($today->diffInDays($lastActivity) === 1) {
            // Consecutive day
            $user->current_streak += 1;
        } else {
            // Streak broken
            $user->current_streak = 1;
        }

        $user->last_activity_at = Carbon::now();
        $user->save();
    }

    public function getDueReviews(User $user, int $limit = 20)
    {
        return SrsReview::where('user_id', $user->id)
            ->where('next_review_at', '<=', Carbon::now())
            ->with(['vocabulary'])
            ->orderBy('next_review_at', 'asc')
            ->limit($limit)
            ->get();
    }
    
    public function getNewCards(User $user, int $limit = 5)
    {
        // Get vocabularies NOT in srs_reviews
        $reviewedIds = SrsReview::where('user_id', $user->id)->pluck('vocabulary_id');
        
        return Vocabulary::whereNotIn('id', $reviewedIds)
            // Ideally filter by User's Level (e.g. N5)
            // ->where('level', $user->level ?? 'N5') 
            ->limit($limit)
            ->get();
    }
}
