<?php

declare(strict_types=1);

namespace App\Services\Studio;

use App\Models\Artwork;
use App\Models\Collection;
use App\Models\NovaCardBackground;
use App\Models\Story;
use App\Models\User;
use App\Support\CoverUrl;
use Illuminate\Support\Collection as SupportCollection;

final class CreatorStudioAssetService
{
    /**
     * @param array<string, mixed> $filters
     */
    public function library(User $user, array $filters = []): array
    {
        $type = $this->normalizeType((string) ($filters['type'] ?? 'all'));
        $source = $this->normalizeSource((string) ($filters['source'] ?? 'all'));
        $sort = $this->normalizeSort((string) ($filters['sort'] ?? 'recent'));
        $query = trim((string) ($filters['q'] ?? ''));
        $page = max(1, (int) ($filters['page'] ?? 1));
        $perPage = min(max((int) ($filters['per_page'] ?? 18), 12), 36);

        $items = $this->allAssets($user);

        if ($type !== 'all') {
            $items = $items->where('type', $type)->values();
        }

        if ($source !== 'all') {
            $items = $items->where('source_key', $source)->values();
        }

        if ($query !== '') {
            $needle = mb_strtolower($query);
            $items = $items->filter(function (array $item) use ($needle): bool {
                return collect([
                    $item['title'] ?? '',
                    $item['type_label'] ?? '',
                    $item['source_label'] ?? '',
                    $item['description'] ?? '',
                ])->contains(fn ($value): bool => is_string($value) && str_contains(mb_strtolower($value), $needle));
            })->values();
        }

        $items = $this->sortAssets($items, $sort);

        $total = $items->count();
        $lastPage = max(1, (int) ceil($total / $perPage));
        $page = min($page, $lastPage);

        return [
            'items' => $items->forPage($page, $perPage)->values()->all(),
            'meta' => [
                'current_page' => $page,
                'last_page' => $lastPage,
                'per_page' => $perPage,
                'total' => $total,
            ],
            'filters' => [
                'type' => $type,
                'source' => $source,
                'sort' => $sort,
                'q' => $query,
            ],
            'type_options' => [
                ['value' => 'all', 'label' => 'All assets'],
                ['value' => 'card_backgrounds', 'label' => 'Card backgrounds'],
                ['value' => 'story_covers', 'label' => 'Story covers'],
                ['value' => 'collection_covers', 'label' => 'Collection covers'],
                ['value' => 'artwork_previews', 'label' => 'Artwork previews'],
                ['value' => 'profile_branding', 'label' => 'Profile branding'],
            ],
            'source_options' => [
                ['value' => 'all', 'label' => 'All sources'],
                ['value' => 'cards', 'label' => 'Nova Cards'],
                ['value' => 'stories', 'label' => 'Stories'],
                ['value' => 'collections', 'label' => 'Collections'],
                ['value' => 'artworks', 'label' => 'Artworks'],
                ['value' => 'profile', 'label' => 'Profile'],
            ],
            'sort_options' => [
                ['value' => 'recent', 'label' => 'Recently updated'],
                ['value' => 'usage', 'label' => 'Most reused'],
                ['value' => 'title', 'label' => 'Title A-Z'],
            ],
            'summary' => $this->summary($items),
            'highlights' => [
                'recent_uploads' => $items->take(5)->values()->all(),
                'most_used' => $items->sortByDesc(fn (array $item): int => (int) ($item['usage_count'] ?? 0))->take(5)->values()->all(),
            ],
        ];
    }

    private function allAssets(User $user): SupportCollection
    {
        return $this->cardBackgrounds($user)
            ->concat($this->storyCovers($user))
            ->concat($this->collectionCovers($user))
            ->concat($this->artworkPreviews($user))
            ->concat($this->profileBranding($user))
            ->sortByDesc(fn (array $item): int => strtotime((string) ($item['created_at'] ?? '')) ?: 0)
            ->values();
    }

    private function cardBackgrounds(User $user): SupportCollection
    {
        return NovaCardBackground::query()
            ->withCount('cards')
            ->where('user_id', $user->id)
            ->latest('created_at')
            ->limit(120)
            ->get()
            ->map(fn (NovaCardBackground $background): array => [
                'id' => 'card-background:' . $background->id,
                'numeric_id' => (int) $background->id,
                'type' => 'card_backgrounds',
                'type_label' => 'Card background',
                'source_key' => 'cards',
                'title' => 'Background #' . $background->id,
                'description' => 'Reusable upload for Nova Card drafts and remixes.',
                'image_url' => $background->processedUrl(),
                'source_label' => 'Nova Cards',
                'usage_count' => (int) ($background->cards_count ?? 0),
                'usage_references' => [
                    ['label' => 'Nova Cards editor', 'href' => route('studio.cards.create')],
                    ['label' => 'Cards library', 'href' => route('studio.cards.index')],
                ],
                'created_at' => $background->created_at?->toIso8601String(),
                'manage_url' => route('studio.cards.index'),
                'view_url' => route('studio.cards.create'),
            ]);
    }

    private function storyCovers(User $user): SupportCollection
    {
        return Story::query()
            ->where('creator_id', $user->id)
            ->whereNotNull('cover_image')
            ->latest('updated_at')
            ->limit(120)
            ->get()
            ->map(fn (Story $story): array => [
                'id' => 'story-cover:' . $story->id,
                'numeric_id' => (int) $story->id,
                'type' => 'story_covers',
                'type_label' => 'Story cover',
                'source_key' => 'stories',
                'title' => $story->title,
                'description' => $story->excerpt ?: 'Cover art attached to a story draft or publication.',
                'image_url' => $story->cover_url,
                'source_label' => 'Stories',
                'usage_count' => 1,
                'usage_references' => [
                    ['label' => 'Story editor', 'href' => route('creator.stories.edit', ['story' => $story->id])],
                ],
                'created_at' => $story->updated_at?->toIso8601String(),
                'manage_url' => route('creator.stories.edit', ['story' => $story->id]),
                'view_url' => in_array($story->status, ['published', 'scheduled'], true)
                    ? route('stories.show', ['slug' => $story->slug])
                    : route('creator.stories.preview', ['story' => $story->id]),
            ]);
    }

    private function collectionCovers(User $user): SupportCollection
    {
        return Collection::query()
            ->with('coverArtwork')
            ->where('user_id', $user->id)
            ->latest('updated_at')
            ->limit(120)
            ->get()
            ->filter(fn (Collection $collection): bool => $collection->coverArtwork !== null)
            ->map(fn (Collection $collection): array => [
                'id' => 'collection-cover:' . $collection->id,
                'numeric_id' => (int) $collection->id,
                'type' => 'collection_covers',
                'type_label' => 'Collection cover',
                'source_key' => 'collections',
                'title' => $collection->title,
                'description' => $collection->summary ?: $collection->description ?: 'Cover artwork used for a collection shelf.',
                'image_url' => $collection->coverArtwork?->thumbUrl('md'),
                'source_label' => 'Collections',
                'usage_count' => 1,
                'usage_references' => [
                    ['label' => 'Collection dashboard', 'href' => route('settings.collections.show', ['collection' => $collection->id])],
                ],
                'created_at' => $collection->updated_at?->toIso8601String(),
                'manage_url' => route('settings.collections.show', ['collection' => $collection->id]),
                'view_url' => route('profile.collections.show', [
                    'username' => strtolower((string) $user->username),
                    'slug' => $collection->slug,
                ]),
            ]);
    }

    private function artworkPreviews(User $user): SupportCollection
    {
        return Artwork::query()
            ->where('user_id', $user->id)
            ->whereNull('deleted_at')
            ->latest('updated_at')
            ->limit(120)
            ->get()
            ->map(fn (Artwork $artwork): array => [
                'id' => 'artwork-preview:' . $artwork->id,
                'numeric_id' => (int) $artwork->id,
                'type' => 'artwork_previews',
                'type_label' => 'Artwork preview',
                'source_key' => 'artworks',
                'title' => $artwork->title ?: 'Untitled artwork',
                'description' => $artwork->description ?: 'Reusable preview image from your artwork library.',
                'image_url' => $artwork->thumbUrl('md'),
                'source_label' => 'Artworks',
                'usage_count' => 1,
                'usage_references' => [
                    ['label' => 'Artwork editor', 'href' => route('studio.artworks.edit', ['id' => $artwork->id])],
                    ['label' => 'Artwork page', 'href' => $artwork->published_at ? route('art.show', ['id' => $artwork->id, 'slug' => $artwork->slug]) : route('studio.artworks.edit', ['id' => $artwork->id])],
                ],
                'created_at' => $artwork->updated_at?->toIso8601String(),
                'manage_url' => route('studio.artworks.edit', ['id' => $artwork->id]),
                'view_url' => $artwork->published_at
                    ? route('art.show', ['id' => $artwork->id, 'slug' => $artwork->slug])
                    : route('studio.artworks.edit', ['id' => $artwork->id]),
            ]);
    }

    private function profileBranding(User $user): SupportCollection
    {
        $items = [];

        if ($user->cover_hash && $user->cover_ext) {
            $items[] = [
                'id' => 'profile-cover:' . $user->id,
                'numeric_id' => (int) $user->id,
                'type' => 'profile_branding',
                'type_label' => 'Profile banner',
                'source_key' => 'profile',
                'title' => 'Profile banner',
                'description' => 'Banner image used on your public creator profile.',
                'image_url' => CoverUrl::forUser($user->cover_hash, $user->cover_ext, time()),
                'source_label' => 'Profile',
                'usage_count' => 1,
                'usage_references' => [
                    ['label' => 'Studio profile', 'href' => route('studio.profile')],
                    ['label' => 'Public profile', 'href' => '/@' . strtolower((string) $user->username)],
                ],
                'created_at' => now()->toIso8601String(),
                'manage_url' => route('studio.profile'),
                'view_url' => '/@' . strtolower((string) $user->username),
            ];
        }

        return collect($items);
    }

    private function summary(SupportCollection $items): array
    {
        return [
            ['key' => 'card_backgrounds', 'label' => 'Card backgrounds', 'count' => $items->where('type', 'card_backgrounds')->count(), 'icon' => 'fa-solid fa-panorama'],
            ['key' => 'story_covers', 'label' => 'Story covers', 'count' => $items->where('type', 'story_covers')->count(), 'icon' => 'fa-solid fa-book-open-cover'],
            ['key' => 'collection_covers', 'label' => 'Collection covers', 'count' => $items->where('type', 'collection_covers')->count(), 'icon' => 'fa-solid fa-layer-group'],
            ['key' => 'artwork_previews', 'label' => 'Artwork previews', 'count' => $items->where('type', 'artwork_previews')->count(), 'icon' => 'fa-solid fa-image'],
            ['key' => 'profile_branding', 'label' => 'Profile branding', 'count' => $items->where('type', 'profile_branding')->count(), 'icon' => 'fa-solid fa-id-badge'],
        ];
    }

    private function normalizeType(string $type): string
    {
        $allowed = ['all', 'card_backgrounds', 'story_covers', 'collection_covers', 'artwork_previews', 'profile_branding'];

        return in_array($type, $allowed, true) ? $type : 'all';
    }

    private function normalizeSource(string $source): string
    {
        $allowed = ['all', 'cards', 'stories', 'collections', 'artworks', 'profile'];

        return in_array($source, $allowed, true) ? $source : 'all';
    }

    private function normalizeSort(string $sort): string
    {
        return in_array($sort, ['recent', 'usage', 'title'], true) ? $sort : 'recent';
    }

    private function sortAssets(SupportCollection $items, string $sort): SupportCollection
    {
        return match ($sort) {
            'usage' => $items->sortByDesc(fn (array $item): int => (int) ($item['usage_count'] ?? 0))->values(),
            'title' => $items->sortBy(fn (array $item): string => mb_strtolower((string) ($item['title'] ?? '')))->values(),
            default => $items->sortByDesc(fn (array $item): int => strtotime((string) ($item['created_at'] ?? '')) ?: 0)->values(),
        };
    }
}