<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\UserBadge;
use App\Models\UserProgress;
use App\Models\Badge;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class ProgressController extends Controller
{
    /**
     * GET /api/user/progress — gamification snapshot (level, points, streak,
     * recently watched).
     */
    public function index()
    {
        $user = Auth::user();

        $recent = UserProgress::where('user_id', $user->id)
            ->orderByDesc('updated_at')
            ->with('content')
            ->limit(10)
            ->get();

        return response()->json([
            'success' => true,
            'data' => [
                'points' => (int) $user->points,
                'level' => (int) $user->level,
                'experience' => (int) $user->experience,
                'next_level_at' => $this->levelThreshold($user->level + 1),
                'recent' => $recent,
            ],
        ]);
    }

    /**
     * POST /api/user/progress
     * Body: content_id, progress_percentage (0..100), last_position (seconds)
     * Idempotent upsert — used by the player every few seconds.
     */
    public function update(Request $request)
    {
        $data = $request->validate([
            'content_id' => ['required','integer','exists:contents,id'],
            'progress_percentage' => ['required','numeric','min:0','max:100'],
            'last_position' => ['nullable','integer','min:0'],
        ]);

        $user = Auth::user();

        $progress = UserProgress::updateOrCreate(
            ['user_id' => $user->id, 'content_id' => $data['content_id']],
            [
                'progress_percentage' => $data['progress_percentage'],
                'last_position' => $data['last_position'] ?? 0,
                'completed' => $data['progress_percentage'] >= 95,
                'completed_at' => $data['progress_percentage'] >= 95 ? now() : null,
            ]
        );

        // Award points on first-time completion
        if ($progress->completed && $progress->wasChanged('completed')) {
            $this->awardPoints($user, 10);
        }

        return response()->json(['success' => true, 'data' => $progress->fresh()]);
    }

    /**
     * POST /api/user/progress/action
     * Body: action (login_daily|view_content|complete_content|share|...) ,
     *       points (override, for admin-supplied actions)
     */
    public function logAction(Request $request)
    {
        $data = $request->validate([
            'action' => ['required','string','max:64'],
            'points' => ['nullable','integer'],
        ]);

        $reward = $data['points'] ?? match ($data['action']) {
            'login_daily' => 3,
            'view_content' => 1,
            'complete_content' => 10,
            'share' => 2,
            default => 0,
        };

        if ($reward !== 0) {
            $this->awardPoints(Auth::user(), $reward);
        }

        return response()->json([
            'success' => true,
            'data' => [
                'awarded' => $reward,
                'points' => Auth::user()->fresh()->points,
                'level' => Auth::user()->fresh()->level,
            ],
        ]);
    }

    /**
     * Awards points and recomputes level. Also auto-grants point-based
     * badges when their threshold is reached.
     */
    protected function awardPoints(User $user, int $delta): void
    {
        DB::transaction(function () use ($user, $delta) {
            $newPoints = (int) $user->points + $delta;
            $newExp = (int) $user->experience + max(0, $delta);
            $newLevel = $this->levelFor($newPoints);

            $user->update([
                'points' => $newPoints,
                'experience' => $newExp,
                'level' => $newLevel,
            ]);

            // Auto-grant point-threshold badges that haven't been granted yet.
            $eligibleBadges = Badge::where('status', 'active')
                ->where('condition_type', 'points')
                ->where('condition_value', '<=', $newPoints)
                ->get();

            foreach ($eligibleBadges as $badge) {
                $exists = UserBadge::where('user_id', $user->id)
                    ->where('badge_id', $badge->id)
                    ->exists();
                if (! $exists) {
                    UserBadge::create([
                        'user_id' => $user->id,
                        'badge_id' => $badge->id,
                        'earned_at' => now(),
                    ]);
                }
            }
        });
    }

    protected function levelFor(int $points): int
    {
        if ($points < 100) return 1;
        if ($points < 300) return 2;
        if ($points < 600) return 3;
        if ($points < 1000) return 4;
        if ($points < 1500) return 5;
        return 6 + intdiv($points - 1500, 700);
    }

    protected function levelThreshold(int $level): int
    {
        return match (true) {
            $level <= 1 => 0,
            $level === 2 => 100,
            $level === 3 => 300,
            $level === 4 => 600,
            $level === 5 => 1000,
            $level === 6 => 1500,
            default => 1500 + ($level - 6) * 700,
        };
    }
}
