<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\User;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

/**
 * UserPreferenceService
 *
 * Builds a lightweight preference profile for a user based on:
 *  - Tags on artworks they have favourited
 *  - Categories of artwork they have favourited / downloaded
 *  - Creators they follow
 *
 * Output shape:
 * [
 *   'top_tags'          => ['space', 'nature', ...],   // up to 5 slugs
 *   'top_categories'    => ['wallpapers', ...],         // up to 3 slugs
 *   'followed_creators' => [1, 5, 23, ...],             // user IDs
 * ]
 */
final class UserPreferenceService
{
    private const CACHE_TTL = 300; // 5 minutes

    public function build(User $user): array
    {
        return Cache::remember(
            "user.prefs.{$user->id}",
            self::CACHE_TTL,
            fn () => $this->compute($user)
        );
    }

    private function compute(User $user): array
    {
        return [
            'top_tags'          => $this->topTags($user),
            'top_categories'    => $this->topCategories($user),
            'followed_creators' => $this->followedCreatorIds($user),
        ];
    }

    /** Top tag slugs derived from the user's favourited artworks */
    private function topTags(User $user, int $limit = 5): array
    {
        return DB::table('artwork_favourites as af')
            ->join('artwork_tag as at', 'at.artwork_id', '=', 'af.artwork_id')
            ->join('tags as t', 't.id', '=', 'at.tag_id')
            ->where('af.user_id', $user->id)
            ->where('t.is_active', true)
            ->selectRaw('t.slug, COUNT(*) as cnt')
            ->groupBy('t.id', 't.slug')
            ->orderByDesc('cnt')
            ->limit($limit)
            ->pluck('slug')
            ->values()
            ->all();
    }

    /** Top category slugs derived from the user's favourited artworks */
    private function topCategories(User $user, int $limit = 3): array
    {
        return DB::table('artwork_favourites as af')
            ->join('artwork_category as ac', 'ac.artwork_id', '=', 'af.artwork_id')
            ->join('categories as c', 'c.id', '=', 'ac.category_id')
            ->where('af.user_id', $user->id)
            ->whereNull('c.deleted_at')
            ->selectRaw('c.slug, COUNT(*) as cnt')
            ->groupBy('c.id', 'c.slug')
            ->orderByDesc('cnt')
            ->limit($limit)
            ->pluck('slug')
            ->values()
            ->all();
    }

    /** IDs of creators the user follows, latest follows first */
    private function followedCreatorIds(User $user, int $limit = 100): array
    {
        return DB::table('user_followers')
            ->where('follower_id', $user->id)
            ->orderByDesc('created_at')
            ->limit($limit)
            ->pluck('user_id')
            ->values()
            ->all();
    }
}
