<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Livewire\Admin\Blog\PostReviews\Manage;
use App\Models\BlogPost;
use App\Models\BlogPostReview;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Spatie\Permission\Models\Role;
use Tests\TestCase;

final class AdminBlogPostReviewsManageTest extends TestCase
{
    use RefreshDatabase;

    public function test_guest_cannot_open_blog_post_review_management(): void
    {
        $this->get(route('admin.blog.post-reviews.index'))
            ->assertRedirect();
    }

    public function test_admin_can_approve_pending_review(): void
    {
        Role::findOrCreate('admin');
        $admin = User::factory()->create();
        $admin->assignRole('admin');

        $post = BlogPost::factory()->create();
        $review = BlogPostReview::factory()->asGuest()->pending()->create([
            'blog_post_id' => $post->id,
            'rating' => 4,
            'body' => 'Waiting for approval.',
        ]);

        $this->assertFalse($review->fresh()->is_approved);

        Livewire::actingAs($admin)
            ->test(Manage::class)
            ->call('approve', $review->id);

        $this->assertTrue($review->fresh()->is_approved);
    }

    public function test_admin_can_save_manual_review_as_approved(): void
    {
        Role::findOrCreate('admin');
        $admin = User::factory()->create();
        $admin->assignRole('admin');

        $post = BlogPost::factory()->create(['title' => 'Manual target']);

        Livewire::actingAs($admin)
            ->test(Manage::class)
            ->set('manualPostId', $post->id)
            ->set('manualGuestName', 'Editorial Name')
            ->set('manualRating', 5)
            ->set('manualBody', 'Manually added copy.')
            ->call('saveManual')
            ->assertHasNoErrors();

        $this->assertDatabaseHas('blog_post_reviews', [
            'blog_post_id' => $post->id,
            'guest_name' => 'Editorial Name',
            'rating' => 5,
            'is_approved' => true,
        ]);
    }

    public function test_admin_can_generate_bulk_reviews_from_manage_screen(): void
    {
        Role::findOrCreate('admin');
        $admin = User::factory()->create();
        $admin->assignRole('admin');

        $post = BlogPost::factory()->create(['title' => 'Bulk review target']);

        Livewire::actingAs($admin)
            ->test(Manage::class)
            ->set('bulkPostId', $post->id)
            ->set('bulkCount', 3)
            ->call('generateBulk')
            ->assertHasNoErrors();

        $this->assertSame(3, BlogPostReview::query()->where('blog_post_id', $post->id)->count());
        $this->assertSame(
            3,
            BlogPostReview::query()->where('blog_post_id', $post->id)->where('is_approved', true)->count()
        );
    }

    public function test_admin_bulk_generate_accepts_optional_date_range(): void
    {
        Role::findOrCreate('admin');
        $admin = User::factory()->create();
        $admin->assignRole('admin');

        $post = BlogPost::factory()->create(['title' => 'Dated bulk']);

        Livewire::actingAs($admin)
            ->test(Manage::class)
            ->set('bulkPostId', $post->id)
            ->set('bulkCount', 5)
            ->set('bulkDateFrom', '2020-01-01')
            ->set('bulkDateTo', '2020-12-31')
            ->call('generateBulk')
            ->assertHasNoErrors();

        $reviews = BlogPostReview::query()->where('blog_post_id', $post->id)->get();
        $this->assertCount(5, $reviews);
        foreach ($reviews as $review) {
            $this->assertSame(2020, (int) $review->created_at->year);
        }
    }
}
