<?php
namespace App\Http\Resources;

use App\Services\ContentSanitizer;
use App\Services\ThumbnailPresenter;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class ArtworkResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     */
    public function toArray($request): array
    {
        $md = ThumbnailPresenter::present($this->resource, 'md');
        $lg = ThumbnailPresenter::present($this->resource, 'lg');
        $xl = ThumbnailPresenter::present($this->resource, 'xl');
        $sq = ThumbnailPresenter::present($this->resource, 'sq');

        $canonicalSlug = \Illuminate\Support\Str::slug((string) ($this->slug ?: $this->title));
        if ($canonicalSlug === '') {
            $canonicalSlug = (string) $this->id;
        }

        $followerCount = 0;
        if (!empty($this->user?->id)) {
            if (Schema::hasTable('user_statistics')) {
                $followerCount = (int) DB::table('user_statistics')
                    ->where('user_id', (int) $this->user->id)
                    ->value('followers_count');
            }

            // Legacy fallback for environments where new tables are unavailable.
            if (($followerCount <= 0) && Schema::hasTable('friends_list')) {
                $followerCount = (int) DB::table('friends_list')
                    ->where('friend_id', (int) $this->user->id)
                    ->count();
            }
        }

        $viewerId = (int) optional($request->user())->id;
        $isLiked = false;
        $isFavorited = false;
        $isBookmarked = false;
        $isFollowing = false;
        $viewerAward = null;

        $bookmarksCount = Schema::hasTable('artwork_bookmarks')
            ? (int) DB::table('artwork_bookmarks')->where('artwork_id', (int) $this->id)->count()
            : 0;

        if ($viewerId > 0) {
            if (Schema::hasTable('artwork_likes')) {
                $isLiked = DB::table('artwork_likes')
                    ->where('user_id', $viewerId)
                    ->where('artwork_id', (int) $this->id)
                    ->exists();
            }

            if (Schema::hasTable('artwork_bookmarks')) {
                $isBookmarked = DB::table('artwork_bookmarks')
                    ->where('user_id', $viewerId)
                    ->where('artwork_id', (int) $this->id)
                    ->exists();
            }

            $isFavorited = DB::table('artwork_favourites')
                ->where('user_id', $viewerId)
                ->where('artwork_id', (int) $this->id)
                ->exists();

            if (!empty($this->user?->id)) {
                if (Schema::hasTable('user_followers')) {
                    $isFollowing = DB::table('user_followers')
                        ->where('user_id', (int) $this->user->id)
                        ->where('follower_id', $viewerId)
                        ->exists();
                } elseif (Schema::hasTable('friends_list')) {
                    // Legacy fallback only.
                    $isFollowing = DB::table('friends_list')
                        ->where('user_id', $viewerId)
                        ->where('friend_id', (int) $this->user->id)
                        ->exists();
                }
            }

            if (Schema::hasTable('artwork_awards')) {
                $viewerAward = DB::table('artwork_awards')
                    ->where('user_id', $viewerId)
                    ->where('artwork_id', (int) $this->id)
                    ->value('medal');
            }
        }

        $decode = static fn (?string $v): string => html_entity_decode((string) ($v ?? ''), ENT_QUOTES | ENT_HTML5, 'UTF-8');

        return [
            'id' => (int) $this->id,
            'slug' => (string) $this->slug,
            'title' => $decode($this->title),
            'description' => $decode($this->description),
            'description_html' => $this->renderDescriptionHtml(),
            'dimensions' => [
                'width' => (int) ($this->width ?? 0),
                'height' => (int) ($this->height ?? 0),
            ],
            'published_at' => optional($this->published_at)->toIsoString(),
            'canonical_url' => route('art.show', ['id' => (int) $this->id, 'slug' => $canonicalSlug]),
            'thumbs' => [
                'md' => $md,
                'lg' => $lg,
                'xl' => $xl,
                'sq' => $sq,
            ],
            'file' => [
                'url' => $lg['url'] ?? null,
                'srcset' => ThumbnailPresenter::srcsetForArtwork($this->resource),
                'mime_type' => 'image/webp',
            ],
            'user' => [
                'id' => (int) ($this->user?->id ?? 0),
                'name' => html_entity_decode((string) ($this->user?->name ?? ''), ENT_QUOTES | ENT_HTML5, 'UTF-8'),
                'username' => (string) ($this->user?->username ?? ''),
                'profile_url' => $this->user?->username ? '/@' . $this->user->username : null,
                'avatar_url' => $this->user?->profile?->avatar_url,
                'level' => (int) ($this->user?->level ?? 1),
                'rank' => (string) ($this->user?->rank ?? 'Newbie'),
                'followers_count' => $followerCount,
            ],
            'viewer' => [
                'is_bookmarked' => $isBookmarked,
                'is_liked' => $isLiked,
                'is_favorited' => $isFavorited,
                'is_following_author' => $isFollowing,
                'is_authenticated' => $viewerId > 0,
                'id' => $viewerId > 0 ? $viewerId : null,
            ],
            'stats' => [
                'bookmarks' => $bookmarksCount,
                'views' => (int) ($this->stats?->views ?? 0),
                'downloads' => (int) ($this->stats?->downloads ?? 0),
                'favorites' => (int) ($this->stats?->favorites ?? 0),
                'likes' => (int) ($this->stats?->rating_count ?? 0),
            ],
            'awards' => [
                'gold' => (int) ($this->awardStat?->gold_count ?? 0),
                'silver' => (int) ($this->awardStat?->silver_count ?? 0),
                'bronze' => (int) ($this->awardStat?->bronze_count ?? 0),
                'score' => (int) ($this->awardStat?->score_total ?? 0),
                'viewer_award' => $viewerAward,
            ],
            'categories' => $this->categories->map(fn ($category) => [
                'id' => (int) $category->id,
                'slug' => (string) $category->slug,
                'name' => html_entity_decode((string) $category->name, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
                'content_type_slug' => (string) ($category->contentType?->slug ?? ''),
                'url' => $category->contentType ? $category->url : null,
                'parent' => $category->parent ? [
                    'id' => (int) $category->parent->id,
                    'slug' => (string) $category->parent->slug,
                    'name' => html_entity_decode((string) $category->parent->name, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
                    'content_type_slug' => (string) ($category->parent->contentType?->slug ?? ''),
                    'url' => $category->parent->contentType ? $category->parent->url : null,
                ] : null,
            ])->values(),
            'tags' => $this->tags->map(fn ($tag) => [
                'id' => (int) $tag->id,
                'slug' => (string) $tag->slug,
                'name' => html_entity_decode((string) $tag->name, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
            ])->values(),
        ];
    }

    private function renderDescriptionHtml(): string
    {
        $rawDescription = (string) ($this->description ?? '');

        if (trim($rawDescription) === '') {
            return '';
        }

        if (! $this->authorCanPublishLinks()) {
            return nl2br(e(ContentSanitizer::stripToPlain($rawDescription)));
        }

        return ContentSanitizer::render($rawDescription);
    }

    private function authorCanPublishLinks(): bool
    {
        $level = (int) ($this->user?->level ?? 1);
        $rank = strtolower((string) ($this->user?->rank ?? 'Newbie'));

        return $level > 1 && $rank !== 'newbie';
    }
}
