<?php

declare(strict_types=1);

namespace App\Http\Controllers\Studio;

use App\Http\Controllers\Controller;
use App\Models\Group;
use App\Models\ContentType;
use App\Services\ArtworkEvolutionService;
use App\Services\Artworks\ArtworkPublicationService;
use App\Services\GroupMembershipService;
use App\Services\GroupService;
use App\Services\Studio\CreatorStudioAnalyticsService;
use App\Services\Studio\CreatorStudioAssetService;
use App\Services\Studio\CreatorStudioCalendarService;
use App\Services\Studio\CreatorStudioCommentService;
use App\Services\Studio\CreatorStudioContentService;
use App\Services\Studio\CreatorStudioFollowersService;
use App\Services\Studio\CreatorStudioGrowthService;
use App\Services\Studio\CreatorStudioActivityService;
use App\Services\Studio\CreatorStudioInboxService;
use App\Services\Studio\CreatorStudioOverviewService;
use App\Services\Studio\CreatorStudioPreferenceService;
use App\Services\Studio\CreatorStudioChallengeService;
use App\Services\Studio\CreatorStudioSearchService;
use App\Services\Studio\CreatorStudioScheduledService;
use App\Services\Worlds\WorldSubmissionService;
use App\Support\CoverUrl;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Inertia\Inertia;
use Inertia\Response;

/**
 * Serves Studio Inertia pages for authenticated creators.
 */
final class StudioController extends Controller
{
    public function __construct(
        private readonly CreatorStudioOverviewService $overview,
        private readonly CreatorStudioContentService $content,
        private readonly CreatorStudioAnalyticsService $analytics,
        private readonly CreatorStudioFollowersService $followers,
        private readonly CreatorStudioCommentService $comments,
        private readonly CreatorStudioAssetService $assets,
        private readonly CreatorStudioPreferenceService $preferences,
        private readonly CreatorStudioScheduledService $scheduled,
        private readonly CreatorStudioActivityService $activity,
        private readonly CreatorStudioCalendarService $calendar,
        private readonly CreatorStudioInboxService $inbox,
        private readonly CreatorStudioSearchService $search,
        private readonly CreatorStudioChallengeService $challenges,
        private readonly CreatorStudioGrowthService $growth,
    ) {}

    /**
     * Studio Overview Dashboard (/studio)
     */
    public function index(Request $request): Response|RedirectResponse
    {
        $user = $request->user();
        $prefs = $this->preferences->forUser($user);

        if (! $request->boolean('overview') && $prefs['default_landing_page'] !== 'overview') {
            return redirect()->route($this->landingPageRoute($prefs['default_landing_page']), $request->query(), 302);
        }

        return Inertia::render('Studio/StudioDashboard', [
            'overview' => $this->overview->build($user),
            'analytics' => $this->analytics->overview($user, $prefs['analytics_range_days']),
        ]);
    }

    public function content(Request $request): Response
    {
        $prefs = $this->preferences->forUser($request->user());
        $listing = $this->content->list($request->user(), $request->only(['module', 'bucket', 'q', 'sort', 'page', 'per_page', 'content_type', 'category', 'tag', 'visibility', 'activity_state', 'stale']));
        $listing['default_view'] = $prefs['default_content_view'];

        return Inertia::render('Studio/StudioContentIndex', [
            'title' => 'Content',
            'description' => 'Manage every artwork, card, collection, and story from one queue.',
            'listing' => $listing,
            'quickCreate' => $this->content->quickCreate(),
        ]);
    }

    /**
     * Artwork Manager (/studio/artworks)
     */
    public function artworks(Request $request): Response
    {
        $provider = $this->content->provider('artworks');
        $prefs = $this->preferences->forUser($request->user());
        $listing = $this->content->list($request->user(), $request->only(['q', 'sort', 'bucket', 'page', 'per_page', 'content_type', 'category', 'tag']), null, 'artworks');
        $listing['default_view'] = $prefs['default_content_view'];

        return Inertia::render('Studio/StudioArtworks', [
            'title' => 'Artworks',
            'description' => 'Upload, manage, and review long-form visual work from the shared Creator Studio workflow.',
            'summary' => $provider?->summary($request->user()),
            'listing' => $listing,
            'quickCreate' => $this->content->quickCreate(),
        ]);
    }

    /**
     * Drafts (/studio/drafts)
     */
    public function drafts(Request $request): Response
    {
        $prefs = $this->preferences->forUser($request->user());
        $listing = $this->content->list($request->user(), $request->only(['module', 'q', 'sort', 'page', 'per_page', 'stale']), 'drafts');
        $listing['default_view'] = $prefs['default_content_view'];

        return Inertia::render('Studio/StudioDrafts', [
            'title' => 'Drafts',
            'description' => 'Resume unfinished work across every creator module.',
            'listing' => $listing,
            'quickCreate' => $this->content->quickCreate(),
        ]);
    }

    public function uploadQueue(Request $request): Response
    {
        $queue = app(\App\Services\Uploads\UploadQueueService::class)->listPayload(
            $request->user(),
            $request->only(['batch_id', 'status', 'sort'])
        );

        return Inertia::render('Studio/StudioUploadQueue', [
            'title' => 'Upload Queue',
            'description' => 'Upload multiple artworks, track processing, and publish only when each draft is ready.',
            'queue' => $queue,
            'contentTypes' => $this->getCategories(),
            'chunkSize' => (int) config('uploads.chunk.max_bytes', 5242880),
            'chunkRequestTimeoutMs' => (int) config('uploads.chunk.request_timeout_ms', 45000),
        ]);
    }

    /**
     * Archived (/studio/archived)
     */
    public function archived(Request $request): Response
    {
        $prefs = $this->preferences->forUser($request->user());
        $listing = $this->content->list($request->user(), $request->only(['module', 'q', 'sort', 'page', 'per_page']), 'archived');
        $listing['default_view'] = $prefs['default_content_view'];

        return Inertia::render('Studio/StudioArchived', [
            'title' => 'Archived',
            'description' => 'Review hidden, rejected, and archived content in one place.',
            'listing' => $listing,
            'quickCreate' => $this->content->quickCreate(),
        ]);
    }

    public function scheduled(Request $request): Response
    {
        $listing = $this->scheduled->list($request->user(), $request->only(['module', 'q', 'page', 'per_page', 'range', 'start_date', 'end_date']));

        return Inertia::render('Studio/StudioScheduled', [
            'title' => 'Scheduled',
            'description' => 'Keep track of upcoming publishes across artworks, cards, collections, and stories.',
            'listing' => $listing,
            'endpoints' => [
                'publishNowPattern' => route('api.studio.schedule.publishNow', ['module' => '__MODULE__', 'id' => '__ID__']),
                'unschedulePattern' => route('api.studio.schedule.unschedule', ['module' => '__MODULE__', 'id' => '__ID__']),
            ],
        ]);
    }

    public function calendar(Request $request): Response
    {
        return Inertia::render('Studio/StudioCalendar', [
            'title' => 'Calendar',
            'description' => 'Plan publishing cadence, spot overloaded days, and move quickly between scheduled work and the unscheduled queue.',
            'calendar' => $this->calendar->build($request->user(), $request->only(['view', 'module', 'status', 'q', 'focus_date'])),
            'endpoints' => [
                'publishNowPattern' => route('api.studio.schedule.publishNow', ['module' => '__MODULE__', 'id' => '__ID__']),
                'unschedulePattern' => route('api.studio.schedule.unschedule', ['module' => '__MODULE__', 'id' => '__ID__']),
            ],
        ]);
    }

    public function collections(Request $request): Response
    {
        $provider = $this->content->provider('collections');
        $prefs = $this->preferences->forUser($request->user());
        $listing = $this->content->list($request->user(), $request->only(['q', 'sort', 'page', 'per_page', 'visibility']), null, 'collections');
        $listing['default_view'] = $prefs['default_content_view'];

        return Inertia::render('Studio/StudioCollections', [
            'title' => 'Collections',
            'description' => 'Curate sets, track collection performance, and keep editorial surfaces organised.',
            'summary' => $provider?->summary($request->user()),
            'listing' => $listing,
            'quickCreate' => $this->content->quickCreate(),
            'dashboardUrl' => route('settings.collections.dashboard'),
        ]);
    }

    public function stories(Request $request): Response
    {
        $provider = $this->content->provider('stories');
        $prefs = $this->preferences->forUser($request->user());
        $listing = $this->content->list($request->user(), $request->only(['q', 'sort', 'page', 'per_page', 'activity_state']), null, 'stories');
        $listing['default_view'] = $prefs['default_content_view'];

        return Inertia::render('Studio/StudioStories', [
            'title' => 'Stories',
            'description' => 'Track drafts, jump into the editor, and monitor story reach from Studio.',
            'summary' => $provider?->summary($request->user()),
            'listing' => $listing,
            'quickCreate' => $this->content->quickCreate(),
            'dashboardUrl' => route('creator.stories.index'),
        ]);
    }

    public function assets(Request $request): Response
    {
        return Inertia::render('Studio/StudioAssets', [
            'title' => 'Assets',
            'description' => 'A reusable creator asset library for card backgrounds, story covers, collection covers, artwork previews, and profile branding.',
            'assets' => $this->assets->library($request->user(), $request->only(['type', 'source', 'sort', 'q', 'page', 'per_page'])),
        ]);
    }

    public function comments(Request $request): Response
    {
        $listing = $this->comments->list($request->user(), $request->only(['module', 'q', 'page', 'per_page']));

        return Inertia::render('Studio/StudioComments', [
            'title' => 'Comments',
            'description' => 'View context, reply in place, remove unsafe comments, and report issues across all of your content.',
            'listing' => $listing,
            'endpoints' => [
                'replyPattern' => route('api.studio.comments.reply', ['module' => '__MODULE__', 'commentId' => '__COMMENT__']),
                'moderatePattern' => route('api.studio.comments.moderate', ['module' => '__MODULE__', 'commentId' => '__COMMENT__']),
                'reportPattern' => route('api.studio.comments.report', ['module' => '__MODULE__', 'commentId' => '__COMMENT__']),
            ],
        ]);
    }

    public function followers(Request $request): Response
    {
        return Inertia::render('Studio/StudioFollowers', [
            'title' => 'Followers',
            'description' => 'See who is following your work, who follows back, and which supporters are most established.',
            'listing' => $this->followers->list($request->user(), $request->only(['q', 'sort', 'relationship', 'page'])),
        ]);
    }

    public function activity(Request $request): Response
    {
        return Inertia::render('Studio/StudioActivity', [
            'title' => 'Activity',
            'description' => 'One creator-facing inbox for notifications, comments, and follower activity.',
            'listing' => $this->activity->list($request->user(), $request->only(['type', 'module', 'q', 'page', 'per_page'])),
            'endpoints' => [
                'markAllRead' => route('api.studio.activity.readAll'),
            ],
        ]);
    }

    public function inbox(Request $request): Response
    {
        return Inertia::render('Studio/StudioInbox', [
            'title' => 'Inbox',
            'description' => 'A creator-first response surface for comments, notifications, followers, reminders, and what needs attention now.',
            'inbox' => $this->inbox->build($request->user(), $request->only(['type', 'module', 'q', 'page', 'per_page', 'read_state', 'priority'])),
            'endpoints' => [
                'markAllRead' => route('api.studio.activity.readAll'),
            ],
        ]);
    }

    public function search(Request $request): Response
    {
        return Inertia::render('Studio/StudioSearch', [
            'title' => 'Search',
            'description' => 'Search across content, comments, inbox signals, and reusable assets without leaving Creator Studio.',
            'search' => $this->search->build($request->user(), $request->only(['q', 'module', 'type'])),
            'quickCreate' => $this->content->quickCreate(),
        ]);
    }

    public function challenges(Request $request): Response
    {
        $data = $this->challenges->build($request->user());

        return Inertia::render('Studio/StudioChallenges', [
            'title' => 'Challenges',
            'description' => 'Track active Nova Cards challenge runs, review your submissions, and keep challenge-ready cards close to hand.',
            'summary' => $data['summary'],
            'spotlight' => $data['spotlight'],
            'activeChallenges' => $data['active_challenges'],
            'recentEntries' => $data['recent_entries'],
            'cardLeaders' => $data['card_leaders'],
            'reminders' => $data['reminders'],
        ]);
    }

    public function growth(Request $request): Response
    {
        $prefs = $this->preferences->forUser($request->user());
        $rangeDays = in_array((int) $request->query('range_days', 0), [7, 14, 30, 60, 90], true)
            ? (int) $request->query('range_days')
            : $prefs['analytics_range_days'];
        $data = $this->growth->build($request->user(), $rangeDays);

        return Inertia::render('Studio/StudioGrowth', [
            'title' => 'Growth',
            'description' => 'A creator-readable view of profile readiness, publishing cadence, engagement momentum, and challenge participation.',
            'summary' => $data['summary'],
            'moduleFocus' => $data['module_focus'],
            'checkpoints' => $data['checkpoints'],
            'opportunities' => $data['opportunities'],
            'milestones' => $data['milestones'],
            'momentum' => $data['momentum'],
            'topContent' => $data['top_content'],
            'rangeDays' => $data['range_days'],
        ]);
    }

    public function profile(Request $request): Response
    {
        $user = $request->user()->loadMissing(['profile', 'statistics']);
        $prefs = $this->preferences->forUser($user);
        $socialLinks = DB::table('user_social_links')
            ->where('user_id', $user->id)
            ->orderBy('platform')
            ->get(['platform', 'url'])
            ->map(fn ($row): array => [
                'platform' => (string) $row->platform,
                'url' => (string) $row->url,
            ])
            ->values()
            ->all();

        return Inertia::render('Studio/StudioProfile', [
            'title' => 'Profile',
            'description' => 'Keep your public creator presence aligned with the work you are publishing.',
            'profile' => [
                'name' => $user->name,
                'username' => $user->username,
                'bio' => $user->profile?->about,
                'tagline' => $user->profile?->description,
                'location' => $user->profile?->country,
                'website' => $user->profile?->website,
                'avatar_url' => $user->profile?->avatar_url,
                'cover_url' => $user->cover_hash && $user->cover_ext ? CoverUrl::forUser($user->cover_hash, $user->cover_ext, time()) : null,
                'cover_position' => (int) ($user->cover_position ?? 50),
                'followers' => (int) ($user->statistics?->followers_count ?? 0),
                'profile_url' => '/@' . strtolower((string) $user->username),
                'social_links' => $socialLinks,
            ],
            'moduleSummaries' => $this->content->moduleSummaries($user),
            'featuredModules' => $prefs['featured_modules'],
            'featuredContent' => $this->content->selectedItems($user, $prefs['featured_content']),
            'endpoints' => [
                'profile' => route('api.studio.preferences.profile'),
                'avatarUpload' => route('avatar.upload'),
                'coverUpload' => route('api.profile.cover.upload'),
                'coverPosition' => route('api.profile.cover.position'),
                'coverDelete' => route('api.profile.cover.destroy'),
            ],
        ]);
    }

    public function featured(Request $request): Response
    {
        $prefs = $this->preferences->forUser($request->user());

        return Inertia::render('Studio/StudioFeatured', [
            'title' => 'Featured',
            'description' => 'Choose the artwork, card, collection, and story that should represent each module on your public profile.',
            'items' => $this->content->featuredCandidates($request->user(), 12),
            'selected' => $prefs['featured_content'],
            'featuredModules' => $prefs['featured_modules'],
            'endpoints' => [
                'save' => route('api.studio.preferences.featured'),
            ],
        ]);
    }

    public function settings(Request $request): Response
    {
        return Inertia::render('Studio/StudioSettings', [
            'title' => 'Settings',
            'description' => 'Keep system handoff links, legacy dashboards, and future Studio control surfaces organized in one place.',
            'links' => [
                ['label' => 'Profile settings', 'url' => route('settings.profile'), 'icon' => 'fa-solid fa-user-gear'],
                ['label' => 'Collection dashboard', 'url' => route('settings.collections.dashboard'), 'icon' => 'fa-solid fa-layer-group'],
                ['label' => 'Story dashboard', 'url' => route('creator.stories.index'), 'icon' => 'fa-solid fa-feather-pointed'],
                ['label' => 'Followers', 'url' => route('dashboard.followers'), 'icon' => 'fa-solid fa-user-group'],
                ['label' => 'Received comments', 'url' => route('dashboard.comments.received'), 'icon' => 'fa-solid fa-comments'],
            ],
            'sections' => [
                [
                    'title' => 'Studio preferences moved into their own surface',
                    'body' => 'Use the dedicated Preferences page for layout, landing page, analytics window, widget order, and shortcut controls.',
                    'href' => route('studio.preferences'),
                    'cta' => 'Open preferences',
                ],
                [
                    'title' => 'Future-ready control points',
                    'body' => 'Notification routing, automation defaults, and collaboration hooks can plug into this settings surface without overloading creator workflow pages.',
                    'href' => route('studio.growth'),
                    'cta' => 'Review growth',
                ],
            ],
        ]);
    }

    public function preferences(Request $request): Response
    {
        $prefs = $this->preferences->forUser($request->user());

        return Inertia::render('Studio/StudioPreferences', [
            'title' => 'Preferences',
            'description' => 'Control how Creator Studio opens, which widgets stay visible, and where your daily workflow starts.',
            'preferences' => $prefs,
            'links' => [
                ['label' => 'Profile settings', 'url' => route('settings.profile'), 'icon' => 'fa-solid fa-user-gear'],
                ['label' => 'Featured content', 'url' => route('studio.featured'), 'icon' => 'fa-solid fa-wand-magic-sparkles'],
                ['label' => 'Growth overview', 'url' => route('studio.growth'), 'icon' => 'fa-solid fa-chart-line'],
                ['label' => 'Studio settings', 'url' => route('studio.settings'), 'icon' => 'fa-solid fa-sliders'],
            ],
            'endpoints' => [
                'save' => route('api.studio.preferences.settings'),
            ],
        ]);
    }

    /**
     * Edit artwork (/studio/artworks/:id/edit)
     */
    public function edit(Request $request, int $id): Response
    {
        $user = $request->user();
        $artwork = $user->artworks()
            ->with(['stats', 'categories.contentType', 'tags', 'artworkAiAssist', 'group.members', 'primaryAuthor.profile', 'contributors.user.profile'])
            ->findOrFail($id);

        $artwork = app(ArtworkPublicationService::class)->publishIfDue($artwork);
        $artwork->loadMissing(['stats', 'categories.contentType', 'tags', 'artworkAiAssist', 'group.members', 'primaryAuthor.profile', 'contributors.user.profile']);

        $primaryCategory = $artwork->categories->first();
        $availableGroups = app(GroupService::class)->studioOptionsForUser($user);
        $membershipService = app(GroupMembershipService::class);
        $contributorOptionsByGroup = [];

        foreach ($availableGroups as $groupOption) {
            $group = Group::query()->with('members')->where('slug', (string) ($groupOption['slug'] ?? ''))->first();
            if (! $group || ! $group->hasActiveMember($user)) {
                continue;
            }

            $contributorOptionsByGroup[(string) $group->slug] = $membershipService->contributorOptions($group);
        }

        return Inertia::render('Studio/StudioArtworkEdit', [
            'artwork'    => [
                'id'              => $artwork->id,
                'title'           => $artwork->title,
                'slug'            => $artwork->slug,
                'description'     => $artwork->description,
                'is_public'       => (bool) $artwork->is_public,
                'visibility'      => $artwork->visibility ?: ((bool) $artwork->is_public ? 'public' : 'private'),
                'is_approved'     => (bool) $artwork->is_approved,
                'publish_mode'    => $artwork->artwork_status === 'scheduled' ? 'schedule' : 'now',
                'publish_at'      => $artwork->publish_at?->toIso8601String(),
                'artwork_status'  => $artwork->artwork_status,
                'artwork_timezone' => $artwork->artwork_timezone,
                'thumb_url'       => $artwork->thumbUrl('md'),
                'thumb_url_lg'    => $artwork->thumbUrl('lg'),
                'download_url'    => route('art.download', ['id' => $artwork->id]),
                'file_name'       => $artwork->file_name,
                'file_ext'        => $artwork->file_ext,
                'file_size'       => $artwork->file_size,
                'width'           => $artwork->width,
                'height'          => $artwork->height,
                'mime_type'       => $artwork->mime_type,
                'has_archive_file' => $this->artworkHasArchiveFile((int) $artwork->id),
                'screenshots'     => $this->screenshotAssetsForArtwork((int) $artwork->id),
                'group_slug'      => $artwork->group?->slug,
                'primary_author_user_id' => (int) ($artwork->primary_author_user_id ?: $artwork->user_id),
                'contributor_user_ids' => $artwork->contributors->pluck('user_id')->map(fn ($id): int => (int) $id)->values()->all(),
                'contributor_credits' => $artwork->contributors->map(fn ($contributor): array => [
                    'user_id' => (int) $contributor->user_id,
                    'credit_role' => $contributor->credit_role,
                    'is_primary' => (bool) $contributor->is_primary,
                ])->values()->all(),
                'content_type_id' => $primaryCategory?->contentType?->id,
                'category_id'     => $primaryCategory?->id,
                'parent_category_id' => $primaryCategory?->parent_id ? $primaryCategory->parent_id : $primaryCategory?->id,
                'sub_category_id'    => $primaryCategory?->parent_id ? $primaryCategory->id : null,
                'categories'      => $artwork->categories->map(fn ($c) => ['id' => $c->id, 'name' => $c->name, 'slug' => $c->slug])->values()->all(),
                'tags'            => $artwork->tags->map(fn ($t) => ['id' => $t->id, 'name' => $t->name, 'slug' => $t->slug])->values()->all(),
                'ai_status'       => $artwork->ai_status,
                'title_source'    => $artwork->title_source ?: 'manual',
                'description_source' => $artwork->description_source ?: 'manual',
                'tags_source'     => $artwork->tags_source ?: 'manual',
                'category_source' => $artwork->category_source ?: 'manual',
                'evolution_relation' => app(ArtworkEvolutionService::class)->editorRelation($artwork, $user),
                // Versioning
                'version_count'       => (int) ($artwork->version_count ?? 1),
                'requires_reapproval' => (bool) $artwork->requires_reapproval,
            ],
            'worldSubmissionOptions' => app(WorldSubmissionService::class)->artworkSubmissionOptions($artwork, $user),
            'contentTypes' => $this->getCategories(),
            'groupOptions' => $availableGroups,
            'contributorOptionsByGroup' => $contributorOptionsByGroup,
            'evolutionRelationTypes' => app(ArtworkEvolutionService::class)->relationTypeOptions(),
        ]);
    }

    /**
     * Analytics v1 (/studio/artworks/:id/analytics)
     */
    public function analytics(Request $request, int $id): Response
    {
        $artwork = $request->user()->artworks()
            ->with(['stats', 'awardStat'])
            ->findOrFail($id);

        $stats = $artwork->stats;

        return Inertia::render('Studio/StudioArtworkAnalytics', [
            'artwork' => [
                'id'            => $artwork->id,
                'title'         => $artwork->title,
                'slug'          => $artwork->slug,
                'thumb_url'     => $artwork->thumbUrl('md'),
            ],
            'analytics' => [
                'views'           => (int) ($stats?->views ?? 0),
                'favourites'      => (int) ($stats?->favorites ?? 0),
                'shares'          => (int) ($stats?->shares_count ?? 0),
                'comments'        => (int) ($stats?->comments_count ?? 0),
                'downloads'       => (int) ($stats?->downloads ?? 0),
                'ranking_score'   => (float) ($stats?->ranking_score ?? 0),
                'heat_score'      => (float) ($stats?->heat_score ?? 0),
                'engagement_velocity' => (float) ($stats?->engagement_velocity ?? 0),
            ],
        ]);
    }

    /**
     * Studio-wide Analytics (/studio/analytics)
     */
    public function analyticsOverview(Request $request): Response
    {
        $user = $request->user();
        $prefs = $this->preferences->forUser($user);
        $rangeDays = in_array((int) $request->query('range_days', 0), [7, 14, 30, 60, 90], true)
            ? (int) $request->query('range_days')
            : $prefs['analytics_range_days'];
        $data = $this->analytics->overview($user, $rangeDays);

        return Inertia::render('Studio/StudioAnalytics', [
            'totals'           => $data['totals'],
            'topContent'       => $data['top_content'],
            'moduleBreakdown'  => $data['module_breakdown'],
            'viewsTrend'       => $data['views_trend'],
            'engagementTrend'  => $data['engagement_trend'],
            'publishingTimeline' => $data['publishing_timeline'],
            'comparison'       => $data['comparison'],
            'insightBlocks'    => $data['insight_blocks'],
            'rangeDays'        => $data['range_days'],
            'recentComments'   => $this->overview->recentComments($user, 8),
        ]);
    }

    private function getCategories(): array
    {
        return ContentType::with(['rootCategories.children'])->ordered()->get()->map(function ($ct) {
            return [
                'id'   => $ct->id,
                'name' => $ct->name,
                'slug' => $ct->slug,
                'categories' => $ct->rootCategories->map(function ($c) {
                    return [
                        'id'       => $c->id,
                        'name'     => $c->name,
                        'slug'     => $c->slug,
                        'children' => $c->children->map(fn ($ch) => [
                            'id'   => $ch->id,
                            'name' => $ch->name,
                            'slug' => $ch->slug,
                        ])->values()->all(),
                    ];
                })->values()->all(),
            ];
        })->values()->all();
    }

    private function landingPageRoute(string $page): string
    {
        return match ($page) {
            'content' => 'studio.content',
            'drafts' => 'studio.drafts',
            'scheduled' => 'studio.scheduled',
            'analytics' => 'studio.analytics',
            'activity' => 'studio.activity',
            'calendar' => 'studio.calendar',
            'inbox' => 'studio.inbox',
            'search' => 'studio.search',
            'growth' => 'studio.growth',
            'challenges' => 'studio.challenges',
            'preferences' => 'studio.preferences',
            default => 'studio.index',
        };
    }

    private function screenshotAssetsForArtwork(int $artworkId): array
    {
        if (! Schema::hasTable('artwork_files')) {
            return [];
        }

        $base = rtrim((string) config('cdn.files_url', 'https://files.skinbase.org'), '/');

        return DB::table('artwork_files')
            ->where('artwork_id', $artworkId)
            ->where('variant', 'like', 'shot%')
            ->orderBy('variant')
            ->get(['variant', 'path', 'mime', 'size'])
            ->map(function ($row, int $index) use ($base): ?array {
                $path = trim((string) ($row->path ?? ''), '/');
                if ($path === '') {
                    return null;
                }

                $url = $base . '/' . $path;

                return [
                    'id' => (string) ($row->variant ?? ('shot' . ($index + 1))),
                    'label' => 'Screenshot ' . ($index + 1),
                    'url' => $url,
                    'thumb_url' => $url,
                    'mime_type' => (string) ($row->mime ?? 'image/jpeg'),
                    'size' => (int) ($row->size ?? 0),
                ];
            })
            ->filter()
            ->values()
            ->all();
    }

    private function artworkHasArchiveFile(int $artworkId): bool
    {
        if (! Schema::hasTable('artwork_files')) {
            return false;
        }

        return DB::table('artwork_files')
            ->where('artwork_id', $artworkId)
            ->where('variant', 'orig_archive')
            ->exists();
    }
}
