<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Artwork;
use App\Models\Tag;
use App\Models\User;
use App\Models\BlogPost;
use App\Services\ThumbnailPresenter;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

/**
 * ErrorSuggestionService
 *
 * Supplies lightweight contextual suggestions for error pages.
 * All queries are cheap, results cached to TTL 5 min.
 */
final class ErrorSuggestionService
{
    private const CACHE_TTL = 300; // 5 minutes

    // ── Trending artworks (max 6) ─────────────────────────────────────────────

    public function trendingArtworks(int $limit = 6): Collection
    {
        $limit = min($limit, 6);

        return Cache::remember("error_suggestions.artworks.{$limit}", self::CACHE_TTL, function () use ($limit) {
            return Artwork::query()
                ->with(['user', 'stats'])
                ->public()
                ->published()
                ->orderByDesc('trending_score_7d')
                ->limit($limit)
                ->get()
                ->map(fn (Artwork $a) => $this->artworkCard($a));
        });
    }

    // ── Similar tags by slug prefix / Levenshtein approximation (max 10) ─────

    public function similarTags(string $slug, int $limit = 10): Collection
    {
        $limit = min($limit, 10);
        $prefix = substr($slug, 0, 3);

        return Cache::remember("error_suggestions.similar_tags.{$slug}.{$limit}", self::CACHE_TTL, function () use ($slug, $limit, $prefix) {
            return Tag::query()
                ->where('slug', '!=', $slug)
                ->where(function ($q) use ($prefix, $slug) {
                    $q->where('slug', 'like', $prefix . '%')
                      ->orWhere('slug', 'like', '%' . substr($slug, -3) . '%');
                })
                ->orderByDesc('artworks_count')
                ->limit($limit)
                ->get(['id', 'name', 'slug', 'artworks_count']);
        });
    }

    // ── Trending tags (max 10) ────────────────────────────────────────────────

    public function trendingTags(int $limit = 10): Collection
    {
        $limit = min($limit, 10);

        return Cache::remember("error_suggestions.tags.{$limit}", self::CACHE_TTL, function () use ($limit) {
            return Tag::query()
                ->orderByDesc('artworks_count')
                ->limit($limit)
                ->get(['id', 'name', 'slug', 'artworks_count']);
        });
    }

    // ── Trending creators (max 6) ─────────────────────────────────────────────

    public function trendingCreators(int $limit = 6): Collection
    {
        $limit = min($limit, 6);

        return Cache::remember("error_suggestions.creators.{$limit}", self::CACHE_TTL, function () use ($limit) {
            return DB::table('users as u')
                ->join('user_statistics as us', 'us.user_id', '=', 'u.id')
                ->leftJoin('user_profiles as up', 'up.user_id', '=', 'u.id')
                ->select('u.id', 'u.name', 'u.username', 'up.avatar_hash', DB::raw('us.uploads_count as artworks_count'))
                ->where('u.is_active', true)
                ->whereNull('u.deleted_at')
                ->where('us.uploads_count', '>', 0)
                ->orderByDesc('us.uploads_count')
                ->limit($limit)
                ->get()
                ->map(fn ($u) => $this->creatorCardFromRow($u));
        });
    }

    // ── Recently joined creators (max 6) ─────────────────────────────────────

    public function recentlyJoinedCreators(int $limit = 6): Collection
    {
        $limit = min($limit, 6);

        return Cache::remember("error_suggestions.creators.recent.{$limit}", self::CACHE_TTL, function () use ($limit) {
            return DB::table('users as u')
                ->join('user_statistics as us', 'us.user_id', '=', 'u.id')
                ->leftJoin('user_profiles as up', 'up.user_id', '=', 'u.id')
                ->select('u.id', 'u.name', 'u.username', 'up.avatar_hash', DB::raw('us.uploads_count as artworks_count'))
                ->where('u.is_active', true)
                ->whereNull('u.deleted_at')
                ->where('us.uploads_count', '>', 0)
                ->orderByDesc('u.id')
                ->limit($limit)
                ->get()
                ->map(fn ($u) => $this->creatorCardFromRow($u));
        });
    }

    // ── Latest blog posts (max 6) ─────────────────────────────────────────────

    public function latestBlogPosts(int $limit = 6): Collection
    {
        $limit = min($limit, 6);

        return Cache::remember("error_suggestions.blog.{$limit}", self::CACHE_TTL, function () use ($limit) {
            return BlogPost::published()
                ->orderByDesc('published_at')
                ->limit($limit)
                ->get(['id', 'title', 'slug', 'excerpt', 'published_at'])
                ->map(fn ($p) => [
                    'id'           => $p->id,
                    'title'        => $p->title,
                    'excerpt'      => Str::limit($p->excerpt ?? '', 100),
                    'url'          => '/blog/' . $p->slug,
                    'published_at' => $p->published_at?->diffForHumans(),
                ]);
        });
    }

    // ── Private helpers ───────────────────────────────────────────────────────

    private function artworkCard(Artwork $a): array
    {
        $slug = Str::slug((string) ($a->slug ?: $a->title)) ?: (string) $a->id;
        $md   = ThumbnailPresenter::present($a, 'md');

        return [
            'id'     => $a->id,
            'title'  => html_entity_decode((string) $a->title, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
            'author' => html_entity_decode((string) ($a->user?->name ?: $a->user?->username ?: 'Artist'), ENT_QUOTES | ENT_HTML5, 'UTF-8'),
            'url'    => route('art.show', ['id' => $a->id, 'slug' => $slug]),
            'thumb'  => $md['url'] ?? null,
            'thumb_srcset' => $md['srcset'] ?? null,
        ];
    }

    private function creatorCard(User $u, int $artworksCount = 0): array
    {
        return [
            'id'             => $u->id,
            'name'           => $u->name ?: $u->username,
            'username'       => $u->username,
            'url'            => '/@' . $u->username,
            'avatar_url'     => \App\Support\AvatarUrl::forUser(
                (int) $u->id,
                optional($u->profile)->avatar_hash,
                64
            ),
            'artworks_count' => $artworksCount,
        ];
    }

    private function creatorCardFromRow(object $u): array
    {
        return [
            'id'             => (int) $u->id,
            'name'           => $u->name ?: $u->username,
            'username'       => $u->username,
            'url'            => '/@' . $u->username,
            'avatar_url'     => \App\Support\AvatarUrl::forUser(
                (int) $u->id,
                $u->avatar_hash ?? null,
                64
            ),
            'artworks_count' => (int) ($u->artworks_count ?? 0),
        ];
    }
}
