<?php

declare(strict_types=1);

namespace App\Services\Sitemaps;

use DateTimeInterface;
use App\Models\Artwork;
use App\Models\Category;
use App\Models\Collection;
use App\Models\ContentType;
use App\Models\NovaCard;
use App\Models\Page;
use App\Models\Story;
use App\Models\Tag;
use App\Models\User;
use App\Models\WorldWebStory;
use App\Services\ThumbnailPresenter;
use cPad\Plugins\Forum\Models\ForumBoard;
use cPad\Plugins\Forum\Models\ForumCategory;
use cPad\Plugins\Forum\Models\ForumTopic;
use cPad\Plugins\News\Models\NewsArticle;
use cPad\Plugins\News\Models\NewsCategory;
use cPad\Plugins\News\Models\NewsTag;
use Illuminate\Support\Str;

final class SitemapUrlBuilder extends AbstractSitemapBuilder
{
    public function name(): string
    {
        return 'url-builder';
    }

    public function items(): array
    {
        return [];
    }

    public function lastModified(): ?\Carbon\CarbonInterface
    {
        return null;
    }

    public function artwork(Artwork $artwork): ?SitemapUrl
    {
        $slug = Str::slug((string) ($artwork->slug ?: $artwork->title));
        if ($slug === '') {
            $slug = (string) $artwork->id;
        }

        $preview = ThumbnailPresenter::present($artwork, 'xl');

        return new SitemapUrl(
            route('art.show', ['id' => (int) $artwork->id, 'slug' => $slug]),
            $this->newest($artwork->updated_at, $artwork->published_at, $artwork->created_at),
            $this->images([
                $this->image($preview['url'] ?? null, (string) $artwork->title),
            ]),
        );
    }

    public function profile(User $user, ?DateTimeInterface $lastModified = null): ?SitemapUrl
    {
        $username = strtolower(trim((string) $user->username));

        if ($username === '') {
            return null;
        }

        return new SitemapUrl(
            route('profile.show', ['username' => $username]),
            $this->newest($lastModified, $user->updated_at, $user->created_at),
        );
    }

    public function tag(Tag $tag): SitemapUrl
    {
        return new SitemapUrl(
            route('tags.show', ['tag' => $tag->slug]),
            $this->newest($tag->updated_at, $tag->created_at),
        );
    }

    public function categoryDirectory(): SitemapUrl
    {
        return new SitemapUrl(route('categories.index'));
    }

    public function contentType(ContentType $contentType): SitemapUrl
    {
        return new SitemapUrl(
            url('/' . strtolower((string) $contentType->slug)),
            $this->newest($contentType->updated_at, $contentType->created_at),
        );
    }

    public function category(Category $category): SitemapUrl
    {
        return new SitemapUrl(
            $this->absoluteUrl($category->url) ?? url('/'),
            $this->newest($category->updated_at, $category->created_at),
        );
    }

    public function collection(Collection $collection): ?SitemapUrl
    {
        $username = strtolower(trim((string) $collection->user?->username));

        if ($username === '' || trim((string) $collection->slug) === '') {
            return null;
        }

        return new SitemapUrl(
            route('profile.collections.show', [
                'username' => $username,
                'slug' => $collection->slug,
            ]),
            $this->newest($collection->updated_at, $collection->published_at, $collection->created_at),
        );
    }

    public function card(NovaCard $card): ?SitemapUrl
    {
        if (trim((string) $card->slug) === '') {
            return null;
        }

        return new SitemapUrl(
            $card->publicUrl(),
            $this->newest($card->updated_at, $card->published_at, $card->created_at),
            $this->images([
                $this->image($card->ogPreviewUrl() ?: $card->previewUrl(), (string) $card->title),
            ]),
        );
    }

    public function story(Story $story): ?SitemapUrl
    {
        if (trim((string) $story->slug) === '') {
            return null;
        }

        return new SitemapUrl(
            $story->url,
            $this->newest($story->updated_at, $story->published_at, $story->created_at),
            $this->images([
                $this->image($story->cover_url ?: $story->og_image, (string) $story->title),
            ]),
        );
    }

    public function news(NewsArticle $article): ?SitemapUrl
    {
        if (trim((string) $article->slug) === '') {
            return null;
        }

        return new SitemapUrl(
            route('news.show', ['slug' => $article->slug]),
            $this->newest($article->updated_at, $article->published_at, $article->created_at),
            $this->images([
                $this->image($article->cover_url ?: $article->effectiveOgImage, (string) $article->title),
            ]),
        );
    }

    public function newsCategory(NewsCategory $category): ?SitemapUrl
    {
        if (trim((string) $category->slug) === '') {
            return null;
        }

        return new SitemapUrl(
            route('news.category', ['slug' => $category->slug]),
            $this->newest($category->updated_at, $category->created_at),
        );
    }

    public function newsTag(NewsTag $tag): ?SitemapUrl
    {
        if (trim((string) $tag->slug) === '') {
            return null;
        }

        return new SitemapUrl(
            route('news.tag', ['slug' => $tag->slug]),
            $this->newest($tag->updated_at, $tag->created_at),
        );
    }

    public function webStory(WorldWebStory $story): ?SitemapUrl
    {
        if (trim((string) $story->slug) === '') {
            return null;
        }

        return new SitemapUrl(
            $story->publicUrl(),
            $this->newest($story->updated_at, $story->published_at, $story->created_at),
            $this->images([
                $this->image($story->posterPortraitUrl(), (string) $story->title),
            ]),
        );
    }

    public function forumIndex(): SitemapUrl
    {
        return new SitemapUrl(route('forum.index'));
    }

    public function forumCategory(ForumCategory $category): SitemapUrl
    {
        return new SitemapUrl(
            route('forum.category.show', ['categorySlug' => $category->slug]),
            $this->newest($category->updated_at, $category->created_at),
        );
    }

    public function forumBoard(ForumBoard $board): SitemapUrl
    {
        return new SitemapUrl(
            route('forum.board.show', ['boardSlug' => $board->slug]),
            $this->newest($board->updated_at, $board->created_at),
        );
    }

    public function forumTopic(ForumTopic $topic): SitemapUrl
    {
        return new SitemapUrl(
            route('forum.topic.show', ['topic' => $topic->slug]),
            $this->newest($topic->last_post_at, $topic->updated_at, $topic->created_at),
        );
    }

    public function staticRoute(string $path, ?\Carbon\CarbonInterface $lastModified = null): SitemapUrl
    {
        return new SitemapUrl(
            url($path),
            $lastModified,
        );
    }

    public function page(Page $page, string $path): SitemapUrl
    {
        return new SitemapUrl(
            url($path),
            $this->newest($page->updated_at, $page->published_at, $page->created_at),
        );
    }
}