<?php
// app/Services/RecommendationCalculator.php

namespace App\Services;

use App\Models\ActivityLog;
use App\Models\Recommendation;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class RecommendationCalculator
{
    /**
     * Hitung durasi rekomendasi berdasarkan kategori dan data historis
     */
    public function calculateDuration($userId, $category, $currentMood, $currentSleep)
    {
        // Base duration per kategori (dibuat variatif)
        $baseDurations = [
            'Ringan' => 30,
            'Sedang' => 45,
            'Intensif' => 80  // Base 80, bukan 90, agar lebih bervariasi
        ];
        
        $baseDuration = $baseDurations[$category];
        
        // Ambil data 7 hari terakhir untuk analisis
        $recentActivities = ActivityLog::where('user_id', $userId)
            ->with('recommendation')
            ->orderBy('activity_date', 'desc')
            ->take(7)
            ->get();
        
        // Jika belum punya history, return base duration dengan variasi ringan
        if ($recentActivities->isEmpty()) {
            $initialVariation = $this->getInitialVariation($category);
            $finalDuration = $baseDuration + $initialVariation;
            $finalDuration = $this->ensureInRange($finalDuration, $category);
            
            return [
                'minutes' => $finalDuration,
                'notes' => $this->generateSimpleNotes($category, $finalDuration),
                'factors' => ['new_user'],
                'adjustment' => $initialVariation,
                'base_duration' => $baseDuration
            ];
        }
        
        // ===========================================
        // FAKTOR-FAKTOR PENYESUAIAN
        // ===========================================
        
        $adjustment = 0;
        $factors = [];
        
        // 1. FAKTOR KONSISTENSI
        $consistencyScore = $this->calculateConsistency($recentActivities);
        if ($consistencyScore > 0.7) {
            $adjustment += 5;
            $factors[] = 'konsisten';
        } elseif ($consistencyScore < 0.3) {
            $adjustment -= 5;
            $factors[] = 'tidak konsisten';
        }
        
        // 2. FAKTOR TREND
        $trend = $this->calculateTrend($recentActivities);
        if ($trend == 'meningkat') {
            $adjustment += 4;
            $factors[] = 'trend meningkat';
        } elseif ($trend == 'menurun') {
            $adjustment -= 4;
            $factors[] = 'trend menurun';
        }
        
        // 3. FAKTOR MOOD
        $moodScore = $this->getMoodWeight($currentMood);
        if ($moodScore >= 1.5) {
            $adjustment += 3;
            $factors[] = 'mood positif';
        } elseif ($moodScore <= 0.5) {
            $adjustment -= 5;
            $factors[] = 'mood negatif';
        }
        
        // 4. FAKTOR TIDUR
        if ($currentSleep >= 7 && $currentSleep <= 9) {
            $adjustment += 3;
            $factors[] = 'tidur ideal';
        } elseif ($currentSleep < 5) {
            $adjustment -= 5;
            $factors[] = 'kurang tidur';
        } elseif ($currentSleep > 9) {
            $adjustment += 1;
            $factors[] = 'tidur panjang';
        }
        
        // 5. FAKTOR BEBAN KOGNITIF
        $intensiveDays = $recentActivities->take(3)
            ->filter(function($activity) {
                return $activity->recommendation && $activity->recommendation->category == 'Intensif';
            })->count();
            
        if ($intensiveDays >= 2) {
            $adjustment -= 5;
            $factors[] = 'perlu recovery';
        }
        
        // 6. FAKTOR ADAPTASI (Individual Differences)
        $avgActual = $recentActivities->avg('duration_minutes');
        $avgRecommended = $recentActivities->filter(function($a) {
                return $a->recommendation;
            })->avg(function($a) {
                return $a->recommendation->recommended_minutes ?? 0;
            });
        
        if ($avgActual > $avgRecommended * 1.2) {
            $adjustment += 5;
            $factors[] = 'kapasitas tinggi';
        } elseif ($avgActual < $avgRecommended * 0.7) {
            $adjustment -= 5;
            $factors[] = 'target terlalu tinggi';
        }
        
        // 7. FAKTOR STREAK (Hari beruntun)
        $streak = $this->calculateStreak($recentActivities);
        if ($streak >= 5) {
            $adjustment += 5;
            $factors[] = 'streak 5+ hari';
        } elseif ($streak >= 3) {
            $adjustment += 3;
            $factors[] = 'streak 3+ hari';
        }
        
        // 8. FAKTOR KESESUAIAN KATEGORI
        $sameCategory = $recentActivities->take(5)
            ->filter(function($a) use ($category) {
                return $a->recommendation && $a->recommendation->category == $category;
            })->count();
            
        if ($sameCategory >= 4) {
            $adjustment += 3;
            $factors[] = 'konsisten di kategori';
        }
        
        // ===========================================
        // VARIASI KHUSUS PER KATEGORI
        // ===========================================
        
        if ($category == 'Intensif') {
            // Variasi untuk Intensif (75-115)
            
            // Berdasarkan durasi aktual
            if ($avgActual > 100) {
                $adjustment += rand(5, 10);
                $factors[] = 'biasa belajar panjang';
            } elseif ($avgActual > 80) {
                $adjustment += rand(0, 5);
                $factors[] = 'cukup terbiasa';
            } else {
                $adjustment -= rand(0, 5);
                $factors[] = 'baru masuk intensif';
            }
            
            // Variasi berdasarkan mood
            if ($currentMood == 'Bagus') {
                $adjustment += rand(2, 5);
            } elseif ($currentMood == 'Lumayan') {
                $adjustment += rand(0, 3);
            }
            
            // Random factor untuk variasi alami (±5)
            $adjustment += rand(-5, 5);
            
        } elseif ($category == 'Sedang') {
            // Variasi untuk Sedang (35-65)
            
            // Berdasarkan trend
            if ($trend == 'meningkat') {
                $adjustment += rand(3, 7);
                $factors[] = 'menuju intensif';
            } elseif ($trend == 'menurun') {
                $adjustment -= rand(3, 7);
                $factors[] = 'menuju ringan';
            }
            
            // Random factor kecil
            $adjustment += rand(-3, 3);
            
        } elseif ($category == 'Ringan') {
            // Variasi untuk Ringan (20-40)
            
            // Jika mood jelek, kurangi
            if ($currentMood == 'Jenuh' || $currentMood == 'Cukup Jenuh') {
                $adjustment -= rand(0, 5);
                $factors[] = 'butuh istirahat';
            }
            
            // Random factor kecil
            $adjustment += rand(-2, 2);
        }
        
        // ===========================================
        // HITUNG DURASI FINAL
        // ===========================================
        
        // Batasi adjustment agar tidak terlalu ekstrim
        $maxAdjustment = $this->getMaxAdjustment($category);
        $adjustment = max(min($adjustment, $maxAdjustment), -$maxAdjustment);
        
        $finalDuration = $baseDuration + $adjustment;
        
        // Bulatkan ke 5 menit terdekat
        $finalDuration = round($finalDuration / 5) * 5;
        
        // Pastikan dalam range yang wajar per kategori
        $finalDuration = $this->ensureInRange($finalDuration, $category);
        
        // Generate notes yang personal
        $notes = $this->generatePersonalNotes($category, $factors, $adjustment, $finalDuration, $streak);
        
        Log::info('Recommendation calculated:', [
            'user_id' => $userId,
            'category' => $category,
            'base' => $baseDuration,
            'adjustment' => $adjustment,
            'final' => $finalDuration,
            'factors' => $factors
        ]);
        
        return [
            'minutes' => $finalDuration,
            'notes' => $notes,
            'factors' => $factors,
            'adjustment' => $adjustment,
            'base_duration' => $baseDuration
        ];
    }
    
    /**
     * Variasi awal untuk user baru
     */
    private function getInitialVariation($category)
    {
        $variations = [
            'Ringan' => rand(-2, 5),
            'Sedang' => rand(-3, 8),
            'Intensif' => rand(-5, 15)
        ];
        
        return $variations[$category];
    }
    
    /**
     * Hitung skor konsistensi (0-1)
     */
    private function calculateConsistency($activities)
    {
        if ($activities->count() < 3) return 0.5;
        
        $durations = $activities->pluck('duration_minutes')->toArray();
        $avg = array_sum($durations) / count($durations);
        
        // Hitung standar deviasi
        $variance = 0;
        foreach ($durations as $dur) {
            $variance += pow($dur - $avg, 2);
        }
        $stdDev = sqrt($variance / count($durations));
        
        // Konsistensi = kebalikan dari koefisien variasi
        $cv = $stdDev / $avg;
        $consistency = max(0, min(1, 1 - $cv));
        
        return $consistency;
    }
    
    /**
     * Hitung trend (meningkat/menurun/stabil)
     */
    private function calculateTrend($activities)
    {
        if ($activities->count() < 4) return 'stabil';
        
        $recent = $activities->take(3)->avg('duration_minutes');
        $older = $activities->slice(3, 3)->avg('duration_minutes');
        
        $diff = $recent - $older;
        
        if ($diff > 10) return 'meningkat';
        if ($diff < -10) return 'menurun';
        return 'stabil';
    }
    
    /**
     * Hitung streak hari beruntun
     */
    private function calculateStreak($activities)
    {
        if ($activities->isEmpty()) return 0;
        
        $streak = 1;
        $prevDate = null;
        
        foreach ($activities as $activity) {
            if ($prevDate) {
                $diff = $prevDate->diffInDays($activity->activity_date);
                if ($diff == 1) {
                    $streak++;
                } else {
                    break;
                }
            }
            $prevDate = $activity->activity_date;
        }
        
        return $streak;
    }
    
    /**
     * Bobot mood (sesuai skema proposal)
     */
    private function getMoodWeight($mood)
    {
        return match($mood) {
            'Bagus' => 2.0,
            'Lumayan' => 1.5,
            'Biasa Saja' => 1.0,
            'Cukup Jenuh' => 0.5,
            'Jenuh' => 0.0,
            default => 1.0
        };
    }
    
    /**
     * Maksimum adjustment per kategori
     */
    private function getMaxAdjustment($category)
    {
        return match($category) {
            'Ringan' => 10,    // 20-40
            'Sedang' => 20,     // 25-65 (lebih lebar)
            'Intensif' => 35,   // 45-115 (sangat lebar)
            default => 15
        };
    }
    
    /**
     * Pastikan durasi dalam range wajar
     */
    private function ensureInRange($duration, $category)
    {
        $ranges = [
            'Ringan' => ['min' => 20, 'max' => 40],
            'Sedang' => ['min' => 30, 'max' => 70],  // Diperlebar
            'Intensif' => ['min' => 60, 'max' => 120] // 60-120
        ];
        
        $range = $ranges[$category];
        
        return max($range['min'], min($duration, $range['max']));
    }
    
    /**
     * Generate notes sederhana untuk user baru
     */
    private function generateSimpleNotes($category, $duration)
    {
        return match($category) {
            'Ringan' => "📚 Belajar ringan {$duration} menit. Selamat datang di LearnMood!",
            'Sedang' => "🎯 Belajar {$duration} menit dengan fokus. Selamat datang!",
            'Intensif' => "🚀 Sesi intensif {$duration} menit. Selamat datang!",
            default => "Selamat datang di LearnMood!"
        };
    }
    
    /**
     * Generate notes personal berdasarkan faktor-faktor
     */
    private function generatePersonalNotes($category, $factors, $adjustment, $duration, $streak)
    {
        $notes = [];
        
        // Base note
        $notes[] = match($category) {
            'Ringan' => "📚 Belajar ringan {$duration} menit",
            'Sedang' => "🎯 Belajar {$duration} menit dengan fokus",
            'Intensif' => "🚀 Sesi intensif {$duration} menit"
        };
        
        // Notes berdasarkan streak
        if ($streak >= 7) {
            $notes[] = "Luar biasa! Streak 7 hari! 🌟";
        } elseif ($streak >= 5) {
            $notes[] = "Hebat! Streak 5 hari! 🔥";
        } elseif ($streak >= 3) {
            $notes[] = "Mantap! Streak 3 hari! ⭐";
        }
        
        // Notes berdasarkan faktor
        if (in_array('konsisten', $factors)) {
            $notes[] = "Konsistensimu luar biasa!";
        }
        
        if (in_array('trend meningkat', $factors)) {
            $notes[] = "Durasi belajarmu terus meningkat!";
        } elseif (in_array('trend menurun', $factors)) {
            $notes[] = "Semangat! Coba tingkatkan lagi.";
        }
        
        if (in_array('mood positif', $factors)) {
            $notes[] = "Mood positif, belajar jadi lebih mudah!";
        } elseif (in_array('mood negatif', $factors)) {
            $notes[] = "Mood sedang kurang, jangan paksakan diri.";
        }
        
        if (in_array('tidur ideal', $factors)) {
            $notes[] = "Tidur cukup mendukung konsentrasi.";
        } elseif (in_array('kurang tidur', $factors)) {
            $notes[] = "Coba tidur lebih awal nanti malam.";
        }
        
        if (in_array('perlu recovery', $factors)) {
            $notes[] = "Beberapa hari ini intensif, jaga keseimbangan.";
        }
        
        if (in_array('kapasitas tinggi', $factors)) {
            $notes[] = "Kamu mampu lebih dari target!";
        } elseif (in_array('target terlalu tinggi', $factors)) {
            $notes[] = "Target mungkin terlalu tinggi, fokus ke kualitas.";
        }
        
        // Khusus Intensif
        if ($category == 'Intensif') {
            if ($duration >= 110) {
                $notes[] = "Wow, super intensif! Pastikan istirahat cukup.";
            } elseif ($duration >= 90) {
                $notes[] = "Sesi intensif optimal! Pertahankan.";
            } elseif ($duration <= 70) {
                $notes[] = "Intensif ringan, bagus untuk adaptasi.";
            }
        }
        
        // Khusus Sedang
        if ($category == 'Sedang' && $duration >= 60) {
            $notes[] = "Hampir masuk intensif! Tingkatkan sedikit lagi.";
        }
        
        // Info adjustment
        if ($adjustment > 5) {
            $notes[] = "(+{$adjustment} menit dari baseline)";
        } elseif ($adjustment < -5) {
            $notes[] = "({$adjustment} menit dari baseline - fokus kualitas)";
        }
        
        return implode(' ', $notes);
    }
}