<?php
// app/Http/Controllers/Siswa/ActivityController.php

namespace App\Http\Controllers\Siswa;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Models\ActivityLog;
use App\Models\Recommendation;
use App\Services\FlaskModelService;
use App\Services\RecommendationCalculator;
use Carbon\Carbon;

class ActivityController extends Controller
{
    protected $flaskService;
    protected $calculator;
    
    public function __construct(FlaskModelService $flaskService, RecommendationCalculator $calculator)
    {
        $this->flaskService = $flaskService;
        $this->calculator = $calculator;
    }
    
    /**
     * Tampilkan form input aktivitas
     */
    public function create()
    {
        // Cek apakah sudah input hari ini
        $todayActivity = ActivityLog::where('user_id', Auth::id())
            ->whereDate('activity_date', Carbon::today())
            ->first();

        if ($todayActivity) {
            return redirect()->route('siswa.input.edit-today')
                ->with('info', 'Kamu sudah menginput aktivitas hari ini. Silakan edit jika ada perubahan.');
        }

        return view('siswa.input');
    }

    /**
     * Tampilkan form edit aktivitas hari ini
     */
    public function editToday()
    {
        $activity = ActivityLog::where('user_id', Auth::id())
            ->whereDate('activity_date', Carbon::today())
            ->first();

        if (!$activity) {
            return redirect()->route('siswa.input')
                ->with('info', 'Belum ada aktivitas hari ini. Silakan input aktivitas dulu.');
        }

        return view('siswa.input', [
            'activity' => $activity,
            'isEdit' => true,
        ]);
    }

    /**
     * Simpan aktivitas dan generate rekomendasi
     */
    public function store(Request $request)
    {
        // Log request data
        Log::info('=== MEMULAI PROSES INPUT ===');
        Log::info('User ID: ' . Auth::id());
        Log::info('Request data: ', $request->all());
        
        // Validasi input
        try {
            $validated = $request->validate([
                'start_time' => 'required',
                'end_time' => 'required|after:start_time',
                'mood' => 'required|in:Bagus,Lumayan,Biasa Saja,Cukup Jenuh,Jenuh',
                'sleep_hours' => 'required|numeric|min:1|max:10',
            ]);
            Log::info('Validasi berhasil');
        } catch (\Exception $e) {
            Log::error('Validasi gagal: ' . $e->getMessage());
            return redirect()->back()
                ->withErrors(['error' => 'Validasi gagal: ' . $e->getMessage()])
                ->withInput();
        }

        try {
            DB::beginTransaction();
            
            $user = Auth::user();

            $todayActivity = ActivityLog::where('user_id', $user->id)
                ->whereDate('activity_date', Carbon::today())
                ->first();

            if ($todayActivity) {
                DB::rollBack();

                return redirect()->route('siswa.input.edit-today')
                    ->with('info', 'Aktivitas hari ini sudah ada. Gunakan form edit untuk memperbarui data.');
            }
            
            // Hitung durasi belajar dalam menit
            $start = Carbon::parse($request->start_time);
            $end = Carbon::parse($request->end_time);
            $durationMinutes = $end->diffInMinutes($start);
            Log::info("Durasi belajar: {$durationMinutes} menit");
            
            // Ambil nilai sleep hours
            $sleepHours = floatval($request->sleep_hours);
            Log::info("Durasi tidur: {$sleepHours} jam");
            
            // Simpan activity
            $activity = ActivityLog::create([
                'user_id' => $user->id,
                'start_time' => $request->start_time,
                'end_time' => $request->end_time,
                'duration_minutes' => $durationMinutes,
                'mood' => $request->mood,
                'sleep_hours' => $sleepHours,
                'activity_date' => Carbon::today(),
            ]);
            
            Log::info('Activity berhasil disimpan dengan ID: ' . $activity->id);
            
            // Hitung total hari user sudah input
            $totalDays = ActivityLog::where('user_id', $user->id)->count();
            Log::info("Total hari input: {$totalDays}");
            
           
            
            // Generate rekomendasi hybrid
            Log::info('Mulai generate rekomendasi...');
            $recommendation = $this->generateHybridRecommendation($user->id, $activity, $totalDays);
            Log::info('Rekomendasi berhasil digenerate dengan ID: ' . $recommendation->id);
            
            DB::commit();
            
            $message = $totalDays <= 7 
                ? "Aktivitas berhasil disimpan! (Mode: Model Harian - Hari ke-{$totalDays}/7)"
                : "Aktivitas berhasil disimpan! (Mode: Pola Siswa - Hari ke-{$totalDays})";
            
            Log::info('=== PROSES SELESAI ===');
            
            // Redirect ke halaman rekomendasi
            return redirect()->route('siswa.recommendations')
                ->with('success', $message);
                
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('ERROR di store: ' . $e->getMessage());
            Log::error('Stack trace: ' . $e->getTraceAsString());
            
            return redirect()->back()
                ->with('error', 'Gagal menyimpan aktivitas: ' . $e->getMessage())
                ->withInput();
        }
    }

    /**
     * Update aktivitas hari ini dan hitung ulang rekomendasi
     */
    public function updateToday(Request $request)
    {
        Log::info('=== MEMULAI PROSES UPDATE AKTIVITAS HARI INI ===');
        Log::info('User ID: ' . Auth::id());
        Log::info('Request data: ', $request->all());

        try {
            $validated = $request->validate([
                'start_time' => 'required',
                'end_time' => 'required|after:start_time',
                'mood' => 'required|in:Bagus,Lumayan,Biasa Saja,Cukup Jenuh,Jenuh',
                'sleep_hours' => 'required|numeric|min:1|max:10',
            ]);
            Log::info('Validasi update berhasil');
        } catch (\Exception $e) {
            Log::error('Validasi update gagal: ' . $e->getMessage());
            return redirect()->back()
                ->withErrors(['error' => 'Validasi gagal: ' . $e->getMessage()])
                ->withInput();
        }

        try {
            DB::beginTransaction();

            $user = Auth::user();
            $activity = ActivityLog::where('user_id', $user->id)
                ->whereDate('activity_date', Carbon::today())
                ->firstOrFail();

            $start = Carbon::parse($request->start_time);
            $end = Carbon::parse($request->end_time);
            $lastEnd = Carbon::parse($activity->end_time);

            if ($start->lt($lastEnd)) {
                DB::rollBack();

                return redirect()->back()
                    ->withErrors(['start_time' => 'Jam mulai tambahan tidak boleh sebelum jam selesai aktivitas sebelumnya.'])
                    ->withInput();
            }

            $additionalMinutes = $end->diffInMinutes($start);
            $durationMinutes = $activity->duration_minutes + $additionalMinutes;
            $sleepHours = floatval($request->sleep_hours);

            $activity->update([
                'start_time' => $activity->start_time,
                'end_time' => $request->end_time,
                'duration_minutes' => $durationMinutes,
                'mood' => $request->mood,
                'sleep_hours' => $sleepHours,
                'activity_date' => Carbon::today(),
            ]);

            $totalDays = ActivityLog::where('user_id', $user->id)->count();
            Log::info("Total hari input setelah update: {$totalDays}");

            $recommendation = $this->generateHybridRecommendation($user->id, $activity, $totalDays);
            Log::info('Rekomendasi berhasil diperbarui dengan ID: ' . $recommendation->id);

            DB::commit();

            return redirect()->route('siswa.recommendations')
                ->with('success', 'Aktivitas hari ini berhasil diperbarui dan rekomendasi sudah dihitung ulang.');

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('ERROR di updateToday: ' . $e->getMessage());
            Log::error('Stack trace: ' . $e->getTraceAsString());

            return redirect()->back()
                ->with('error', 'Gagal memperbarui aktivitas: ' . $e->getMessage())
                ->withInput();
        }
    }
    
    /**
     * Generate rekomendasi hybrid berdasarkan jumlah hari
     */
    private function generateHybridRecommendation($userId, $activity, $totalDays)
    {
        $recommendation = [];
        $message = '';
        
        if ($totalDays <= 7) {
            // 7 HARI PERTAMA: Gunakan model harian (Flask)
            Log::info("Hari ke-{$totalDays}: Menggunakan model harian");
            
            $result = $this->flaskService->predictDaily(
                $activity->mood,
                $activity->duration_minutes,
                $activity->sleep_hours
            );
            
            if ($result['success']) {
                // ✅ FLASK SUKSES - dapat kategori dari ML
                $category = $result['category'];
                
                // Hitung durasi personal dengan calculator
                $durationResult = $this->calculator->calculateDuration(
                    $userId,
                    $category,
                    $activity->mood,
                    $activity->sleep_hours
                );
                
                $recommendation = [
                    'category' => $category,
                    'recommended_minutes' => $durationResult['minutes'],
                    'notes' => $durationResult['notes'],
                    'based_on' => 'daily_model',
                    'confidence' => $result['confidence'] ?? null,
                    'factors' => $durationResult['factors'] ?? [],
                    'adjustment' => $durationResult['adjustment'] ?? 0
                ];
                $message = 'Rekomendasi berdasarkan model harian dengan penyesuaian personal.';
                
                Log::info("ML Prediction: {$category}, Durasi personal: {$durationResult['minutes']} menit");
                
            } else {
                // ❌ FLASK GAGAL - fallback ke aturan manual
                Log::warning('Flask API gagal, menggunakan aturan manual');
                
                $manualResult = $this->generateManualRecommendation($activity);
                
                // Hitung durasi personal untuk manual result
                $durationResult = $this->calculator->calculateDuration(
                    $userId,
                    $manualResult['category'],
                    $activity->mood,
                    $activity->sleep_hours
                );
                
                $recommendation = [
                    'category' => $manualResult['category'],
                    'recommended_minutes' => $durationResult['minutes'],
                    'notes' => $durationResult['notes'] . ' (Fallback manual)',
                    'based_on' => 'manual_rules',
                    'confidence' => null,
                    'factors' => $durationResult['factors'] ?? [],
                    'adjustment' => $durationResult['adjustment'] ?? 0
                ];
                $message = 'Rekomendasi berdasarkan aturan manual (model server sedang maintenance).';
            }
            
        } else {
            // HARI KE-8 dst: Gunakan pola siswa
            Log::info("Hari ke-{$totalDays}: Menggunakan pola siswa");
            
            $result = $this->flaskService->predictBasedOnPattern($userId);
            
            if ($result['success']) {
                // ✅ ANALISIS POLA SUKSES
                $category = $result['category'];
                
                // Hitung durasi personal dengan calculator (dengan data pola)
                $durationResult = $this->calculator->calculateDuration(
                    $userId,
                    $category,
                    $activity->mood,
                    $activity->sleep_hours
                );
                
                $recommendation = [
                    'category' => $category,
                    'recommended_minutes' => $durationResult['minutes'],
                    'notes' => $durationResult['notes'],
                    'based_on' => 'student_pattern',
                    'pattern_analysis' => $result['pattern_analysis'] ?? null,
                    'factors' => $durationResult['factors'] ?? [],
                    'adjustment' => $durationResult['adjustment'] ?? 0
                ];
                $message = 'Rekomendasi berdasarkan pola belajarmu selama 7 hari terakhir.';
                
            } else {
                // ❌ ANALISIS POLA GAGAL - fallback ke model harian
                Log::warning('Pattern analysis gagal, fallback ke model harian');
                
                $dailyResult = $this->flaskService->predictDaily(
                    $activity->mood,
                    $activity->duration_minutes,
                    $activity->sleep_hours
                );
                
                if ($dailyResult['success']) {
                    $category = $dailyResult['category'];
                    
                    $durationResult = $this->calculator->calculateDuration(
                        $userId,
                        $category,
                        $activity->mood,
                        $activity->sleep_hours
                    );
                    
                    $recommendation = [
                        'category' => $category,
                        'recommended_minutes' => $durationResult['minutes'],
                        'notes' => $durationResult['notes'] . ' (Fallback dari pola)',
                        'based_on' => 'daily_model_fallback',
                        'confidence' => $dailyResult['confidence'] ?? null,
                        'factors' => $durationResult['factors'] ?? [],
                        'adjustment' => $durationResult['adjustment'] ?? 0
                    ];
                    $message = 'Rekomendasi berdasarkan model harian (analisis pola belum tersedia).';
                    
                } else {
                    // 🚨 FALLBACK TERAKHIR - aturan manual
                    Log::warning('Semua fallback gagal, menggunakan aturan manual');
                    
                    $manualResult = $this->generateManualRecommendation($activity);
                    
                    $durationResult = $this->calculator->calculateDuration(
                        $userId,
                        $manualResult['category'],
                        $activity->mood,
                        $activity->sleep_hours
                    );
                    
                    $recommendation = [
                        'category' => $manualResult['category'],
                        'recommended_minutes' => $durationResult['minutes'],
                        'notes' => $durationResult['notes'] . ' (Fallback darurat)',
                        'based_on' => 'emergency_fallback',
                        'confidence' => null,
                        'factors' => $durationResult['factors'] ?? [],
                        'adjustment' => $durationResult['adjustment'] ?? 0
                    ];
                    $message = 'Rekomendasi berdasarkan aturan dasar.';
                }
            }
        }
        
        // PASTIKAN ARRAY $recommendation PUNYA SEMUA KEY YANG DIPERLUKAN
        if (!isset($recommendation['based_on'])) {
            $recommendation['based_on'] = 'unknown';
            Log::warning('based_on tidak diset, menggunakan default unknown');
        }
        
        // Simpan atau perbarui rekomendasi untuk aktivitas ini
        $savedRec = Recommendation::updateOrCreate([
            'activity_log_id' => $activity->id,
        ], [
            'user_id' => $userId,
            'category' => $recommendation['category'],
            'recommended_minutes' => $recommendation['recommended_minutes'],
            'notes' => $recommendation['notes'],
            'based_on' => $recommendation['based_on'],
            'confidence' => $recommendation['confidence'] ?? null,
            'model_input' => json_encode([
                'mood' => $activity->mood,
                'duration_minutes' => $activity->duration_minutes,
                'sleep_hours' => $activity->sleep_hours,
                'total_days' => $totalDays,
                'factors' => $recommendation['factors'] ?? [],
                'adjustment' => $recommendation['adjustment'] ?? 0,
                'pattern_analysis' => $recommendation['pattern_analysis'] ?? null
            ]),
            'recommendation_date' => Carbon::today(),
        ]);
        
        Log::info('Rekomendasi tersimpan:', [
            'id' => $savedRec->id,
            'category' => $savedRec->category,
            'minutes' => $savedRec->recommended_minutes,
            'based_on' => $savedRec->based_on
        ]);
        
        return $savedRec;
    }
    
    /**
     * Generate rekomendasi manual (fallback)
     */
    private function generateManualRecommendation($activity)
    {
        // Hitung skor manual berdasarkan proposal
        $moodScore = match($activity->mood) {
            'Bagus' => 2.0,
            'Lumayan' => 1.5,
            'Biasa Saja' => 1.0,
            'Cukup Jenuh' => 0.5,
            'Jenuh' => 0.0,
            default => 1.0
        };
        
        $durationScore = $activity->duration_minutes > 60 ? 2.0 : ($activity->duration_minutes >= 31 ? 1.0 : 0.0);
        $sleepScore = $activity->sleep_hours >= 7 ? 2.0 : ($activity->sleep_hours >= 4 ? 1.0 : 0.0);
        
        $totalScore = $moodScore + $durationScore + $sleepScore;
        
        // Tentukan kategori berdasarkan total skor
        if ($totalScore > 4.5) {
            $category = 'Intensif';
        } elseif ($totalScore > 3) {
            $category = 'Sedang';
        } else {
            $category = 'Ringan';
        }
        
        Log::info('Manual recommendation:', [
            'scores' => [$moodScore, $durationScore, $sleepScore],
            'total' => $totalScore,
            'category' => $category
        ]);
        
        return [
            'category' => $category,
            'based_on' => 'manual_rules'
        ];
    }
    
    /**
     * Helper untuk mendapatkan durasi base dari kategori
     */
    private function getMinutesFromCategory($category)
    {
        return match($category) {
            'Ringan' => 30,
            'Sedang' => 45,
            'Intensif' => 90,
            default => 30
        };
    }
    
    /**
     * Generate notes untuk daily model (tidak dipakai langsung karena calculator sudah generate notes)
     */
    private function generateDailyNotes($result, $day, $activity)
    {
        $category = $result['category'];
        $confidence = $result['confidence'] ?? 0;
        
        $notes = "Hari ke-{$day} belajar. ";
        
        $sleepQuality = $this->getSleepQuality($activity->sleep_hours);
        
        $notes .= match($category) {
            'Ringan' => "Kondisi kamu kurang fit (tidur {$activity->sleep_hours} jam - {$sleepQuality}).",
            'Sedang' => "Kamu dalam kondisi cukup baik (tidur {$activity->sleep_hours} jam - {$sleepQuality}).",
            'Intensif' => "Kondisi kamu sangat baik (tidur {$activity->sleep_hours} jam - {$sleepQuality})!",
            default => 'Tetap semangat belajar!'
        };
        
        if ($confidence > 0.9) {
            $notes .= ' Prediksi dengan keyakinan tinggi.';
        }
        
        return $notes;
    }
    
    /**
     * Helper untuk kualitas tidur
     */
    private function getSleepQuality($hours)
    {
        if ($hours < 5) return 'kurang tidur';
        if ($hours < 7) return 'kurang ideal';
        if ($hours <= 9) return 'ideal';
        return 'berlebih';
    }
    
    /**
     * Tampilkan history aktivitas
     */
    public function history(Request $request)
    {
        $user = Auth::user();
        
        // Ambil parameter filter
        $period = $request->get('period', 'all'); // all, 7, 30, 90
        $mood = $request->get('mood', 'all');
        $search = $request->get('search', '');
        
        // Query dasar
        $query = ActivityLog::where('user_id', $user->id)
            ->with('recommendation')
            ->orderBy('activity_date', 'desc');
        
        // Filter periode
        if ($period == '7') {
            $query->whereDate('activity_date', '>=', Carbon::today()->subDays(7));
        } elseif ($period == '30') {
            $query->whereDate('activity_date', '>=', Carbon::today()->subDays(30));
        } elseif ($period == '90') {
            $query->whereDate('activity_date', '>=', Carbon::today()->subDays(90));
        }
        
        // Filter mood
        if ($mood != 'all') {
            $query->where('mood', $mood);
        }
        
        // Pencarian (di notes)
        if (!empty($search)) {
            $query->where('notes', 'like', '%' . $search . '%');
        }
        
        // Ambil data dengan pagination
        $activities = $query->paginate(15)->withQueryString();
        
        // Statistik untuk header
        $stats = [
            'total' => ActivityLog::where('user_id', $user->id)->count(),
            'total_duration' => ActivityLog::where('user_id', $user->id)->sum('duration_minutes'),
            'avg_duration' => round(ActivityLog::where('user_id', $user->id)->avg('duration_minutes') ?? 0),
            'consistency' => $this->calculateConsistency($user->id),
        ];
        
        // Daftar mood untuk filter dropdown
        $moodList = ['Bagus', 'Lumayan', 'Biasa Saja', 'Cukup Jenuh', 'Jenuh'];
        
        return view('siswa.history', compact('activities', 'stats', 'period', 'mood', 'search', 'moodList'));
    }

    private function calculateConsistency($userId)
{
    $total = ActivityLog::where('user_id', $userId)->count();
    if ($total == 0) return 0;
    
    $firstDate = ActivityLog::where('user_id', $userId)->min('activity_date');
    if (!$firstDate) return 0;
    
    $daysDiff = Carbon::parse($firstDate)->diffInDays(Carbon::today()) + 1;
    
    return round(($total / $daysDiff) * 100);
}
}
