<?php

namespace Tests\Unit\Models;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use App\Models\Blog;
use App\Models\Category;
use App\Models\User;
use Tests\TestCase;

class BlogTest extends TestCase
{
    private User|Collection $user;
    public $category;
    protected function setUp(): void
    {
        parent::setUp();

        $this->user = User::factory()->create();
        $this->category = Category::factory()->create();
    }

    /** @test */
    public function it_can_create_a_blog_with_factory(): void
    {
        $blog = Blog::factory()->create();

        $this->assertInstanceOf(Blog::class, $blog);
        $this->assertIsString($blog->post);
        $this->assertIsString($blog->slug);
    }

    /** @test */
    public function it_has_correct_fillable_attributes(): void
    {
        $blogData = [
            'post' => 'Test Blog Post',
            'slug' => 'test-blog-post',
            'content' => 'This is the blog content.',
            'meta' => json_encode(['description' => 'Meta description', 'keywords' => 'keyword1,keyword2']),
            'custom_header' => 'Blog excerpt',
            'post_image' => 'blog-image.jpg',
            'is_published' => true,
            'category_id' => $this->category->id,
        ];

        $blog = Blog::query()->create($blogData);

        foreach ($blogData as $key => $value) {
            $this->assertEquals($value, $blog->$key);
        }
    }

    /** @test */
    public function it_belongs_to_a_category(): void
    {
        $blog = Blog::factory()->create(['category_id' => $this->category->id]);

        $this->assertInstanceOf(Category::class, $blog->category);
        $this->assertEquals($this->category->id, $blog->category->id);
    }

    /** @test */
    public function it_generates_unique_slugs(): void
    {
        $blog1 = Blog::factory()->create(['post' => 'Same Title']);
        $blog2 = Blog::factory()->create(['post' => 'Same Title']);

        $this->assertNotEquals($blog1->slug, $blog2->slug);
    }

    /** @test */
    public function it_can_query_published_blogs(): void
    {
        Blog::factory()->create(['is_published' => true]);
        Blog::factory()->create(['is_published' => false]);

        $publishedBlogs = Blog::query()->where('is_published', true)->get();
        $draftBlogs = Blog::query()->where('is_published', false)->get();

        $this->assertCount(1, $publishedBlogs);
        $this->assertCount(1, $draftBlogs);
    }

    /** @test */
    public function it_can_create_blogs_with_custom_headers(): void
    {
        $blog = Blog::factory()->create(['custom_header' => 'Custom Header Text']);

        $this->assertEquals('Custom Header Text', $blog->custom_header);
    }

    /** @test */
    public function it_orders_blogs_by_creation_date(): void
    {
        $oldBlog = Blog::factory()->create(['created_at' => now()->subDays(2)]);
        $newBlog = Blog::factory()->create(['created_at' => now()]);

        $blogs = Blog::query()->latest()->get();

        $this->assertEquals($newBlog->id, $blogs->first()->id);
        $this->assertEquals($oldBlog->id, $blogs->last()->id);
    }

    /** @test */
    public function it_handles_long_content(): void
    {
        $longContent = str_repeat('This is a very long blog content. ', 100);

        $blog = Blog::factory()->create(['content' => $longContent]);

        $this->assertEquals($longContent, $blog->content);
        $this->assertGreaterThan(1000, strlen((string) $blog->content));
    }

    /** @test */
    public function it_can_update_blog_status(): void
    {
        $blog = Blog::factory()->create(['is_published' => false]);

        $blog->update(['is_published' => true]);

        $blog->refresh();
        $this->assertEquals(true, $blog->is_published);
    }

    /** @test */
    public function it_scopes_blogs_by_category(): void
    {
        $category1 = Category::factory()->create();
        $category2 = Category::factory()->create();

        Blog::factory()->create(['category_id' => $category1->id]);
        Blog::factory()->create(['category_id' => $category1->id]);
        Blog::factory()->create(['category_id' => $category2->id]);

        $category1Blogs = Blog::query()->where('category_id', $category1->id)->get();
        $category2Blogs = Blog::query()->where('category_id', $category2->id)->get();

        $this->assertCount(2, $category1Blogs);
        $this->assertCount(1, $category2Blogs);
    }

    /** @test */
    public function it_uses_correct_table_name(): void
    {
        $blog = new Blog;

        $this->assertEquals('blogs', $blog->getTable());
    }

    /** @test */
    public function it_extends_model_class(): void
    {
        $blog = new Blog;

        $this->assertInstanceOf(Model::class, $blog);
    }
}
