<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Collection;
use App\Models\User;
use Illuminate\Support\Collection as SupportCollection;

class CollectionSeriesService
{
    public function __construct(
        private readonly CollectionService $collections,
    ) {
    }

    public function updateSeries(Collection $collection, array $attributes, ?User $actor = null): Collection
    {
        return $this->collections->updateCollection(
            $collection->loadMissing('user'),
            $this->normalizeAttributes($attributes),
            $actor,
        );
    }

    public function metadataFor(Collection|SupportCollection $seriesSource): array
    {
        $items = $seriesSource instanceof Collection
            ? collect([$seriesSource])->when($seriesSource->series_key, fn (SupportCollection $current) => $current->concat($this->publicSeriesItems((string) $seriesSource->series_key)))
            : $seriesSource;

        $metaSource = $items
            ->first(fn (Collection $item) => filled($item->series_title) || filled($item->series_description));

        return [
            'title' => $metaSource?->series_title,
            'description' => $metaSource?->series_description,
        ];
    }

    public function seriesContext(Collection $collection): array
    {
        if (! $collection->inSeries()) {
            return [
                'key' => null,
                'title' => null,
                'description' => null,
                'items' => [],
                'previous' => null,
                'next' => null,
            ];
        }

        $items = Collection::query()
            ->public()
            ->where('series_key', $collection->series_key)
            ->with(['user:id,username,name', 'coverArtwork:id,user_id,title,slug,hash,thumb_ext,published_at,is_public,is_approved,deleted_at'])
            ->orderBy('series_order')
            ->orderBy('id')
            ->get();

        $index = $items->search(fn (Collection $item) => (int) $item->id === (int) $collection->id);

        return [
            'key' => $collection->series_key,
            'title' => $this->metadataFor($items->prepend($collection))['title'],
            'description' => $this->metadataFor($items->prepend($collection))['description'],
            'items' => $items,
            'previous' => $index !== false && $index > 0 ? $items->get($index - 1) : null,
            'next' => $index !== false ? $items->get($index + 1) : null,
        ];
    }

    public function publicSeriesItems(string $seriesKey): SupportCollection
    {
        return Collection::query()
            ->public()
            ->where('series_key', $seriesKey)
            ->with(['user:id,username,name', 'coverArtwork:id,user_id,title,slug,hash,thumb_ext,published_at,is_public,is_approved,deleted_at'])
            ->orderByRaw('CASE WHEN series_order IS NULL THEN 1 ELSE 0 END')
            ->orderBy('series_order')
            ->orderBy('id')
            ->get();
    }

    public function summary(Collection $collection): array
    {
        $context = $collection->inSeries()
            ? $this->seriesContext($collection)
            : ['key' => null, 'title' => null, 'description' => null, 'items' => [], 'previous' => null, 'next' => null];

        return [
            'key' => $context['key'] ?? $collection->series_key,
            'title' => $context['title'] ?? $collection->series_title,
            'description' => $context['description'] ?? $collection->series_description,
            'order' => $collection->series_order,
            'siblings_count' => max(0, count($context['items'] ?? [])),
            'previous_id' => $context['previous']?->id,
            'next_id' => $context['next']?->id,
            'public_url' => filled($collection->series_key)
                ? route('collections.series.show', ['seriesKey' => $collection->series_key])
                : null,
        ];
    }

    private function normalizeAttributes(array $attributes): array
    {
        if (blank($attributes['series_key'] ?? null)) {
            return [
                'series_key' => null,
                'series_title' => null,
                'series_description' => null,
                'series_order' => null,
            ];
        }

        return $attributes;
    }
}
