<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Domain\Ai\Jobs\GenerateArticleCoverJob;
use App\Domain\Media\ArticleCoverService;
use App\Models\Article;
use App\Models\Attachment;
use App\Models\Category;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class ArticleCoverTest extends TestCase
{
    use RefreshDatabase;

    protected string $attachmentsRoot;

    protected function setUp(): void
    {
        parent::setUp();

        $this->attachmentsRoot = storage_path('framework/testing/attachments-'.uniqid());
        File::ensureDirectoryExists($this->attachmentsRoot);

        config([
            'filesystems.disks.attachments' => [
                'driver' => 'local',
                'root' => $this->attachmentsRoot,
                'url' => rtrim((string) config('app.url'), '/').'/attachments-local',
                'visibility' => 'public',
                'throw' => true,
            ],
            'larablog.attachments_disk' => 'attachments',
        ]);
    }

    protected function tearDown(): void
    {
        if (isset($this->attachmentsRoot) && is_dir($this->attachmentsRoot)) {
            File::deleteDirectory($this->attachmentsRoot);
        }

        parent::tearDown();
    }

    public function test_auto_cover_from_markdown_remote_image(): void
    {
        $article = $this->makeArticle([
            'content' => "Hello\n\n![cover](https://cdn.example.com/hero.jpg)\n\nMore text",
        ]);

        app(ArticleCoverService::class)->apply($article, 'auto');
        $article->refresh();

        $this->assertTrue($article->hasCover());
        $this->assertSame(ArticleCoverService::SOURCE_CONTENT_IMAGE, $article->cover_source);
        $this->assertSame('url', $article->cover_disk);
        $this->assertSame('https://cdn.example.com/hero.jpg', $article->coverUrl());
    }

    public function test_auto_cover_from_attachment_when_no_body_image(): void
    {
        $article = $this->makeArticle(['content' => 'No images here']);

        Attachment::query()->create([
            'article_id' => $article->id,
            'disk' => 'attachments',
            'path' => 'covers/demo.png',
            'filename' => 'demo.png',
            'mime' => 'image/png',
            'size' => 12,
            'visibility' => Attachment::VISIBILITY_PUBLIC,
        ]);

        (new GenerateArticleCoverJob($article->id, 'auto'))
            ->handle(app(ArticleCoverService::class));

        $article->refresh();
        $this->assertTrue($article->hasCover());
        $this->assertSame(ArticleCoverService::SOURCE_ATTACHMENT, $article->cover_source);
        $this->assertSame('covers/demo.png', $article->cover_path);
    }

    public function test_generate_strategy_renders_template_cover(): void
    {
        $article = $this->makeArticle([
            'title' => 'Template Cover Smoke',
            'description' => 'A short blurb for the generated cover card.',
        ]);

        (new GenerateArticleCoverJob($article->id, 'generate'))
            ->handle(app(ArticleCoverService::class));

        $article->refresh();
        $this->assertTrue($article->hasCover());
        $this->assertSame(ArticleCoverService::SOURCE_GENERATED, $article->cover_source);
        $this->assertTrue(Storage::disk('attachments')->exists((string) $article->cover_path));
        $this->assertGreaterThan(1000, Storage::disk('attachments')->size((string) $article->cover_path));
        $this->assertSame(1, Attachment::query()->where('article_id', $article->id)->count());
    }

    /**
     * @param  array<string, mixed>  $overrides
     */
    protected function makeArticle(array $overrides = []): Article
    {
        $user = User::factory()->create();
        $category = Category::query()->create(['name' => 'Cover', 'display_order' => 0]);

        return Article::query()->create(array_merge([
            'category_id' => $category->id,
            'user_id' => $user->id,
            'title' => 'Cover post',
            'content' => 'Body',
            'content_format' => 'markdown',
            'published_at' => now()->subMinute(),
            'visible' => true,
        ], $overrides));
    }
}
