<?php

declare(strict_types=1);

namespace App\Http\Controllers\Studio;

use App\Http\Controllers\Controller;
use App\Models\Artwork;
use App\Models\Collection;
use App\Models\NovaCard;
use App\Models\Story;
use App\Services\Artworks\ArtworkPublicationService;
use App\Services\CollectionLifecycleService;
use App\Services\NovaCards\NovaCardPublishService;
use App\Services\StoryPublicationService;
use App\Services\Studio\CreatorStudioContentService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

final class StudioScheduleApiController extends Controller
{
    public function __construct(
        private readonly CreatorStudioContentService $content,
        private readonly ArtworkPublicationService $artworkPublication,
        private readonly NovaCardPublishService $cards,
        private readonly CollectionLifecycleService $collections,
        private readonly StoryPublicationService $stories,
    ) {
    }

    public function publishNow(Request $request, string $module, int $id): JsonResponse
    {
        $user = $request->user();

        match ($module) {
            'artworks' => $this->publishArtworkNow($user->id, $id),
            'cards' => $this->cards->publishNow($this->card($user->id, $id)),
            'collections' => $this->publishCollectionNow($user->id, $id),
            'stories' => $this->stories->publish($this->story($user->id, $id), 'published', ['published_at' => now()]),
            default => abort(404),
        };

        return response()->json([
            'ok' => true,
            'item' => $this->serializedItem($request->user(), $module, $id),
        ]);
    }

    public function unschedule(Request $request, string $module, int $id): JsonResponse
    {
        $user = $request->user();

        match ($module) {
            'artworks' => $this->unscheduleArtwork($user->id, $id),
            'cards' => $this->cards->clearSchedule($this->card($user->id, $id)),
            'collections' => $this->unscheduleCollection($user->id, $id),
            'stories' => $this->unscheduleStory($user->id, $id),
            default => abort(404),
        };

        return response()->json([
            'ok' => true,
            'item' => $this->serializedItem($request->user(), $module, $id),
        ]);
    }

    private function publishArtworkNow(int $userId, int $id): void
    {
        $artwork = Artwork::query()
            ->where('user_id', $userId)
            ->findOrFail($id);

        $this->artworkPublication->publishNow($artwork);
    }

    private function unscheduleArtwork(int $userId, int $id): void
    {
        Artwork::query()
            ->where('user_id', $userId)
            ->findOrFail($id)
            ->forceFill([
                'artwork_status' => 'draft',
                'publish_at' => null,
                'artwork_timezone' => null,
                'published_at' => null,
            ])
            ->save();
    }

    private function publishCollectionNow(int $userId, int $id): void
    {
        $collection = Collection::query()
            ->where('user_id', $userId)
            ->findOrFail($id);

        $this->collections->applyAttributes($collection, [
            'published_at' => now(),
            'lifecycle_state' => Collection::LIFECYCLE_PUBLISHED,
        ]);
    }

    private function unscheduleCollection(int $userId, int $id): void
    {
        $collection = Collection::query()
            ->where('user_id', $userId)
            ->findOrFail($id);

        $this->collections->applyAttributes($collection, [
            'published_at' => null,
            'lifecycle_state' => Collection::LIFECYCLE_DRAFT,
        ]);
    }

    private function unscheduleStory(int $userId, int $id): void
    {
        Story::query()
            ->where('creator_id', $userId)
            ->findOrFail($id)
            ->forceFill([
                'status' => 'draft',
                'scheduled_for' => null,
                'published_at' => null,
            ])
            ->save();
    }

    private function card(int $userId, int $id): NovaCard
    {
        return NovaCard::query()
            ->where('user_id', $userId)
            ->findOrFail($id);
    }

    private function story(int $userId, int $id): Story
    {
        return Story::query()
            ->where('creator_id', $userId)
            ->findOrFail($id);
    }

    private function serializedItem($user, string $module, int $id): ?array
    {
        return $this->content->provider($module)?->items($user, 'all', 400)
            ->first(fn (array $item): bool => (int) ($item['numeric_id'] ?? 0) === $id);
    }
}