<?php

declare(strict_types=1);

use App\Models\User;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Config;
use cPad\Plugins\News\Models\NewsArticle;
use cPad\Plugins\News\Models\NewsCategory;
use cPad\Plugins\News\Models\NewsTag;

function newsCategory(array $attributes = []): NewsCategory
{
    return NewsCategory::query()->create(array_merge([
        'name' => 'Platform Updates',
        'slug' => 'platform-updates-' . Str::lower(Str::random(6)),
        'description' => 'Skinbase platform updates.',
        'position' => 0,
        'is_active' => true,
    ], $attributes));
}

function newsTag(array $attributes = []): NewsTag
{
    return NewsTag::query()->create(array_merge([
        'name' => 'Launch',
        'slug' => 'launch-' . Str::lower(Str::random(6)),
    ], $attributes));
}

function publishedNewsArticle(User $author, NewsCategory $category, array $attributes = []): NewsArticle
{
    $article = NewsArticle::query()->create(array_merge([
        'title' => 'Nova newsroom launch',
        'slug' => 'nova-newsroom-launch-' . Str::lower(Str::random(6)),
        'excerpt' => 'A first-party newsroom for launches, tutorials, and editorials.',
        'content' => "# Nova newsroom\n\nThis is the first newsroom article.",
        'author_id' => $author->id,
        'category_id' => $category->id,
        'type' => NewsArticle::TYPE_PLATFORM_UPDATE,
        'status' => 'published',
        'editorial_status' => NewsArticle::EDITORIAL_STATUS_PUBLISHED,
        'published_at' => now()->subHour(),
        'is_featured' => true,
        'is_pinned' => true,
    ], $attributes));

    return $article;
}

it('renders published news across public discovery routes', function (): void {
    $author = User::factory()->create([
        'username' => 'newsauthor',
        'name' => 'News Author',
    ]);
    $category = newsCategory([
        'name' => 'Announcements',
        'slug' => 'announcements',
    ]);
    $tag = newsTag([
        'name' => 'Release',
        'slug' => 'release',
    ]);
    $article = publishedNewsArticle($author, $category, [
        'title' => 'Skinbase Newsroom',
        'slug' => 'skinbase-newsroom',
    ]);
    $article->tags()->sync([$tag->id]);

    publishedNewsArticle($author, $category, [
        'title' => 'Hidden Draft',
        'slug' => 'hidden-draft',
        'status' => 'draft',
        'editorial_status' => NewsArticle::EDITORIAL_STATUS_DRAFT,
        'published_at' => null,
        'is_featured' => false,
        'is_pinned' => false,
    ]);

    $this->get(route('news.index'))
        ->assertOk()
        ->assertSee('Skinbase Newsroom')
        ->assertDontSee('Hidden Draft');

    $this->get(route('news.show', ['slug' => $article->slug]))
        ->assertOk()
        ->assertSee('Skinbase Newsroom')
        ->assertSee('News Author');

    $this->get(route('news.category', ['slug' => $category->slug]))
        ->assertOk()
        ->assertSee('Skinbase Newsroom');

    $this->get(route('news.tag', ['slug' => $tag->slug]))
        ->assertOk()
        ->assertSee('Skinbase Newsroom');

    $this->get(route('news.archive', ['year' => $article->published_at->year, 'month' => $article->published_at->month]))
        ->assertOk()
        ->assertSee('Skinbase Newsroom');

    $this->get(route('news.author', ['username' => $author->username]))
        ->assertOk()
        ->assertSee('Skinbase Newsroom');
});

it('renders news index breadcrumbs and item list schema', function (): void {
    $author = User::factory()->create([
        'username' => 'indexschemaauthor',
        'name' => 'Index Schema Author',
    ]);

    $category = newsCategory([
        'name' => 'Announcements',
        'slug' => 'announcements-index-schema',
    ]);

    $article = publishedNewsArticle($author, $category, [
        'title' => 'Index Schema Article',
        'slug' => 'index-schema-article',
    ]);

    $this->get(route('news.index'))
        ->assertOk()
        ->assertSeeInOrder(['Home', 'News'])
        ->assertSee('CollectionPage', false)
        ->assertSee('ItemList', false)
        ->assertSee(route('news.show', ['slug' => $article->slug]), false);
});

it('shows only popular news topics in the sidebar and links to the full tags page', function (): void {
    config()->set('news.sidebar_tags_limit', 2);

    $author = User::factory()->create([
        'username' => 'sidebarauthor',
        'name' => 'Sidebar Author',
    ]);
    $category = newsCategory([
        'name' => 'Sidebar Category',
        'slug' => 'sidebar-category',
    ]);

    $tagAlpha = newsTag([
        'name' => 'Alpha Topic',
        'slug' => 'alpha-topic',
    ]);
    $tagBeta = newsTag([
        'name' => 'Beta Topic',
        'slug' => 'beta-topic',
    ]);
    $tagGamma = newsTag([
        'name' => 'Gamma Topic',
        'slug' => 'gamma-topic',
    ]);

    $articleOne = publishedNewsArticle($author, $category, [
        'title' => 'Sidebar article one',
        'slug' => 'sidebar-article-one',
        'is_featured' => false,
        'is_pinned' => false,
    ]);
    $articleOne->tags()->sync([$tagAlpha->id, $tagBeta->id]);

    $articleTwo = publishedNewsArticle($author, $category, [
        'title' => 'Sidebar article two',
        'slug' => 'sidebar-article-two',
        'is_featured' => false,
        'is_pinned' => false,
        'published_at' => now()->subMinutes(30),
    ]);
    $articleTwo->tags()->sync([$tagAlpha->id]);

    $articleThree = publishedNewsArticle($author, $category, [
        'title' => 'Sidebar article three',
        'slug' => 'sidebar-article-three',
        'is_featured' => false,
        'is_pinned' => false,
        'published_at' => now()->subMinutes(15),
    ]);
    $articleThree->tags()->sync([$tagGamma->id]);

    $this->get(route('news.index'))
        ->assertOk()
        ->assertSee('Popular Topics')
        ->assertSee('All Tags')
        ->assertSee(route('tags.index'), false)
        ->assertSee('#Alpha Topic')
        ->assertSee('#Beta Topic')
        ->assertDontSee('#Gamma Topic');
});

it('renders a public news article when anonymous sessions are skipped', function (): void {
    Config::set('skinbase-sessions.enabled', true);
    Config::set('skinbase-sessions.debug_header', true);

    $author = User::factory()->create([
        'username' => 'guestnewsauthor',
        'name' => 'Guest News Author',
    ]);

    $category = newsCategory([
        'name' => 'Guest Announcements',
        'slug' => 'guest-announcements',
    ]);

    $article = publishedNewsArticle($author, $category, [
        'title' => 'Guest Sessionless News Page',
        'slug' => 'guest-sessionless-news-page',
    ]);

    $this->get(route('news.show', ['slug' => $article->slug]))
        ->assertOk()
        ->assertHeader('X-Skinbase-Session', 'skipped')
        ->assertSee('Guest Sessionless News Page');
});

it('renders article breadcrumbs with home news category hierarchy', function (): void {
    $author = User::factory()->create([
        'username' => 'breadcrumbauthor',
        'name' => 'Breadcrumb Author',
    ]);

    $category = newsCategory([
        'name' => 'Technology',
        'slug' => 'technology',
    ]);

    $article = publishedNewsArticle($author, $category, [
        'title' => 'Breadcrumb Check Article',
        'slug' => 'breadcrumb-check-article',
    ]);

    $this->get(route('news.show', ['slug' => $article->slug]))
        ->assertOk()
        ->assertSeeInOrder(['Home', 'News', 'Technology']);
});

it('renders category breadcrumbs and item list schema', function (): void {
    $author = User::factory()->create([
        'username' => 'categoryschemaauthor',
        'name' => 'Category Schema Author',
    ]);

    $category = newsCategory([
        'name' => 'Technology',
        'slug' => 'technology-schema',
    ]);

    $article = publishedNewsArticle($author, $category, [
        'title' => 'Category Schema Article',
        'slug' => 'category-schema-article',
    ]);

    $this->get(route('news.category', ['slug' => $category->slug]))
        ->assertOk()
        ->assertSeeInOrder(['Home', 'News', 'Technology'])
        ->assertSee('CollectionPage', false)
        ->assertSee('ItemList', false)
        ->assertSee(route('news.show', ['slug' => $article->slug]), false);
});

it('renders structured data for public news pages', function (): void {
    $author = User::factory()->create([
        'username' => 'schemaauthor',
        'name' => 'Schema Author',
    ]);

    $category = newsCategory([
        'name' => 'Technology',
        'slug' => 'technology-structured-data',
    ]);

    $tag = newsTag([
        'name' => 'Game Art',
        'slug' => 'game-art-structured-data',
    ]);

    $article = publishedNewsArticle($author, $category, [
        'title' => 'Structured Data Article',
        'slug' => 'structured-data-article',
    ]);
    $article->tags()->sync([$tag->id]);

    $this->get(route('news.index'))
        ->assertOk()
        ->assertSee('CollectionPage', false)
        ->assertSee('BreadcrumbList', false)
        ->assertSee('ItemList', false);

    $this->get(route('news.category', ['slug' => $category->slug]))
        ->assertOk()
        ->assertSee('CollectionPage', false)
        ->assertSee('BreadcrumbList', false)
        ->assertSee('ItemList', false);

    $this->get(route('news.tag', ['slug' => $tag->slug]))
        ->assertOk()
        ->assertSee('CollectionPage', false)
        ->assertSee('BreadcrumbList', false);

    $this->get(route('news.archive', ['year' => $article->published_at->year, 'month' => $article->published_at->month]))
        ->assertOk()
        ->assertSee('CollectionPage', false)
        ->assertSee('BreadcrumbList', false);

    $this->get(route('news.author', ['username' => $author->username]))
        ->assertOk()
        ->assertSee('CollectionPage', false)
        ->assertSee('BreadcrumbList', false);

    $this->get(route('news.show', ['slug' => $article->slug]))
        ->assertOk()
        ->assertSee('NewsArticle', false)
        ->assertSee('ImageObject', false)
        ->assertSee('creditText', false)
        ->assertSee('copyrightNotice', false)
        ->assertSee('creator', false)
        ->assertSee(route('profile.show', ['username' => $author->username]), false)
        ->assertSee(route('terms-of-service'), false)
        ->assertSee('acquireLicensePage', false)
        ->assertSee('BreadcrumbList', false);
});

it('prioritizes the news hero image and skips the grid stylesheet on article pages', function (): void {
    $author = User::factory()->create([
        'username' => 'lcpauthor',
        'name' => 'LCP Author',
    ]);

    $category = newsCategory([
        'name' => 'Performance',
        'slug' => 'performance-news',
    ]);

    $article = publishedNewsArticle($author, $category, [
        'title' => 'Performance News Article',
        'slug' => 'performance-news-article',
        'cover_image' => 'news/covers/ab/cd/abcdef1234567890.webp',
    ]);

    $response = $this->get(route('news.show', ['slug' => $article->slug]));

    $response
        ->assertOk()
        ->assertSee('fetchpriority="high"', false)
        ->assertSee('loading="eager"', false)
        ->assertSee('imagesizes="(max-width: 767px) calc(100vw - 3rem), (max-width: 1279px) calc(100vw - 5rem), 768px"', false)
        ->assertSee(' 768w', false)
        ->assertSee('href="' . e($article->cover_desktop_url ?? $article->cover_url) . '"', false)
        ->assertDontSee('id="news-cover-preview"', false)
        ->assertDontSee('resources/css/nova-grid.css', false);
});