<?php

namespace App\Services\Engagement;

use App\Models\InAppNotification;
use App\Modules\Users\Models\User;

/**
 * مستويات: beginner → explorer → pro → elite.
 */
final class UserLevelService
{
    private const ORDER = ['beginner' => 0, 'explorer' => 1, 'pro' => 2, 'elite' => 3];

    public function sync(User $user): ?string
    {
        $slug = $this->resolveSlug((int) $user->ai_message_count, (int) $user->reward_points);
        $previous = (string) $user->level_slug;
        if ($slug === $previous) {
            return null;
        }

        $tierUp = (self::ORDER[$slug] ?? 0) > (self::ORDER[$previous] ?? 0);
        $user->level_slug = $slug;
        $user->save();

        if ($tierUp) {
            InAppNotification::query()->create([
                'user_id' => $user->id,
                'type' => 'level_up',
                'title' => 'ترقية مستوى',
                'body' => 'أصبحت الآن: '.$this->labelAr($slug),
                'data' => ['level_slug' => $slug],
            ]);

            return $slug;
        }

        return null;
    }

    public function summary(User $user): array
    {
        $slug = (string) $user->level_slug;
        $msgs = (int) $user->ai_message_count;
        $pts = (int) $user->reward_points;

        $next = $this->nextThreshold($slug, $msgs, $pts);

        return [
            'level_slug' => $slug,
            'level_label_ar' => $this->labelAr($slug),
            'ai_message_count' => $msgs,
            'reward_points' => $pts,
            'login_streak' => (int) $user->login_streak,
            'longest_login_streak' => (int) $user->longest_login_streak,
            'next_level_slug' => $next['slug'],
            'next_level_label_ar' => $next['slug'] !== null ? $this->labelAr((string) $next['slug']) : null,
            'progress_messages' => $next['messages'],
            'progress_points' => $next['points'],
        ];
    }

    private function resolveSlug(int $messages, int $points): string
    {
        if ($messages >= 200 || $points >= 10000) {
            return 'elite';
        }
        if ($messages >= 50 || $points >= 2000) {
            return 'pro';
        }
        if ($messages >= 10 || $points >= 500) {
            return 'explorer';
        }

        return 'beginner';
    }

    /**
     * @return array{slug: ?string, messages: array{current: int, need: int|null}, points: array{current: int, need: int|null}}
     */
    private function nextThreshold(string $current, int $messages, int $points): array
    {
        return match ($current) {
            'beginner' => [
                'slug' => 'explorer',
                'messages' => ['current' => $messages, 'need' => max(0, 10 - $messages)],
                'points' => ['current' => $points, 'need' => max(0, 500 - $points)],
            ],
            'explorer' => [
                'slug' => 'pro',
                'messages' => ['current' => $messages, 'need' => max(0, 50 - $messages)],
                'points' => ['current' => $points, 'need' => max(0, 2000 - $points)],
            ],
            'pro' => [
                'slug' => 'elite',
                'messages' => ['current' => $messages, 'need' => max(0, 200 - $messages)],
                'points' => ['current' => $points, 'need' => max(0, 10000 - $points)],
            ],
            default => [
                'slug' => null,
                'messages' => ['current' => $messages, 'need' => null],
                'points' => ['current' => $points, 'need' => null],
            ],
        };
    }

    private function labelAr(string $slug): string
    {
        return match ($slug) {
            'explorer' => 'مستكشف',
            'pro' => 'محترف',
            'elite' => 'نخبة',
            default => 'مبتدئ',
        };
    }
}
