<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Models\Course;
use App\Models\ExamAttempt;
use App\Models\Material;
use App\Models\Referral;
use App\Models\Subscription;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;

class DashboardController extends Controller
{
    public function index(Request $request): View
    {
        $user = $request->user();

        $activeSubscription = Subscription::with('plan')
            ->where('user_id', $user->id)
            ->where('status', 'active')
            ->where(function ($query) {
                $query->whereNull('expires_at')
                    ->orWhere('expires_at', '>=', now());
            })
            ->latest()
            ->first();

        $attemptsQuery = ExamAttempt::with('exam')
            ->where('user_id', $user->id);

        $recentAttempts = (clone $attemptsQuery)
            ->latest()
            ->take(5)
            ->get();

        $completedAttempts = (clone $attemptsQuery)
            ->where('status', 'submitted')
            ->whereNotNull('percentage');

        $averageScore = (float) (clone $completedAttempts)->avg('percentage');
        $totalAttempts = (clone $attemptsQuery)->count();
        $referralCount = Referral::where('referrer_id', $user->id)->count();

        $stats = [
            'courses' => Course::where('is_active', true)->count(),
            'materials' => Material::where('is_active', true)->count(),
            'attempts' => $totalAttempts,
            'referrals' => $referralCount,
            'active_subscription' => $activeSubscription,
            'average_score' => round($averageScore, 1),
            'readiness' => min(100, round($averageScore > 0 ? (($averageScore * 0.7) + min($totalAttempts, 20)) : 0)),
            'study_streak' => $this->calculateStudyStreak($user->id),
            'referral_tier' => $this->resolveReferralTier($referralCount),
        ];

        $performanceTrend = $this->buildPerformanceTrend($user->id);
        $coursePerformance = $this->buildCoursePerformance($user->id);
        $studyConsistency = $this->buildStudyConsistency($user->id);
        $attemptDistribution = $this->buildAttemptDistribution($user->id);
        $referralGrowth = $this->buildReferralGrowth($user->id);

        return view('user.dashboard', compact(
            'stats',
            'recentAttempts',
            'performanceTrend',
            'coursePerformance',
            'studyConsistency',
            'attemptDistribution',
            'referralGrowth'
        ));
    }

    protected function buildPerformanceTrend(int $userId): array
    {
        $attempts = ExamAttempt::where('user_id', $userId)
            ->where('status', 'submitted')
            ->whereNotNull('percentage')
            ->latest()
            ->take(8)
            ->get()
            ->reverse()
            ->values();

        return [
            'categories' => $attempts->map(fn ($attempt) => $attempt->created_at->format('M d'))->values(),
            'series' => $attempts->map(fn ($attempt) => round((float) $attempt->percentage, 1))->values(),
        ];
    }

    protected function buildCoursePerformance(int $userId): array
    {
        $rows = DB::table('exam_attempts')
            ->join('exams', 'exam_attempts.exam_id', '=', 'exams.id')
            ->leftJoin('courses', 'exams.course_id', '=', 'courses.id')
            ->where('exam_attempts.user_id', $userId)
            ->where('exam_attempts.status', 'submitted')
            ->whereNotNull('exam_attempts.percentage')
            ->selectRaw('COALESCE(courses.name, "General") as course_name, AVG(exam_attempts.percentage) as avg_percentage')
            ->groupBy('course_name')
            ->orderBy('course_name')
            ->limit(8)
            ->get();

        return [
            'categories' => $rows->pluck('course_name')->values(),
            'series' => $rows->pluck('avg_percentage')->map(fn ($value) => round((float) $value, 1))->values(),
        ];
    }

    protected function buildStudyConsistency(int $userId): array
    {
        $days = collect(range(6, 0))->map(function ($offset) use ($userId) {
            $date = Carbon::today()->subDays($offset);

            $count = ExamAttempt::where('user_id', $userId)
                ->whereDate('created_at', $date)
                ->count();

            return [
                'label' => $date->format('D'),
                'minutes' => $count * 25,
            ];
        });

        return [
            'categories' => $days->pluck('label')->values(),
            'series' => $days->pluck('minutes')->values(),
        ];
    }

    protected function buildAttemptDistribution(int $userId): array
    {
        $passed = ExamAttempt::where('user_id', $userId)
            ->where('status', 'submitted')
            ->where('percentage', '>=', 50)
            ->count();

        $needsReview = ExamAttempt::where('user_id', $userId)
            ->where('status', 'submitted')
            ->where('percentage', '<', 50)
            ->count();

        $incomplete = ExamAttempt::where('user_id', $userId)
            ->where('status', '!=', 'submitted')
            ->count();

        return [
            'labels' => ['Passed', 'Needs Review', 'Incomplete'],
            'series' => [$passed, $needsReview, $incomplete],
        ];
    }

    protected function buildReferralGrowth(int $userId): array
    {
        $months = collect(range(5, 0))->map(function ($offset) {
            $date = Carbon::now()->startOfMonth()->subMonths($offset);

            return [
                'key' => $date->format('Y-m'),
                'label' => $date->format('M'),
            ];
        });

        $counts = Referral::where('referrer_id', $userId)
            ->where('created_at', '>=', Carbon::now()->startOfMonth()->subMonths(5))
            ->selectRaw('DATE_FORMAT(created_at, "%Y-%m") as month_key, COUNT(*) as total')
            ->groupBy('month_key')
            ->pluck('total', 'month_key');

        return [
            'categories' => $months->pluck('label')->values(),
            'series' => $months->map(fn ($month) => (int) ($counts[$month['key']] ?? 0))->values(),
        ];
    }

    protected function calculateStudyStreak(int $userId): int
    {
        $streak = 0;

        foreach (range(0, 30) as $offset) {
            $date = Carbon::today()->subDays($offset);

            $hasActivity = ExamAttempt::where('user_id', $userId)
                ->whereDate('created_at', $date)
                ->exists();

            if ($hasActivity) {
                $streak++;
            } else {
                break;
            }
        }

        return $streak;
    }

    protected function resolveReferralTier(int $count): string
    {
        return match (true) {
            $count >= 20 => 'Elite',
            $count >= 10 => 'Gold',
            $count >= 5 => 'Silver',
            default => 'Starter',
        };
    }
}