<?php

namespace Tests\Unit\Jobs;

use App\Jobs\ArticleDiscoveryJob;
use App\Models\Setting;
use App\Services\Log\LogSaver;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
use Mockery;
use Tests\TestCase;

class ArticleDiscoveryJobTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        Queue::fake();
    }

    public function test_constructor_sets_correct_queue(): void
    {
        // Act
        $job = new ArticleDiscoveryJob;

        // Assert
        $this->assertEquals('feed-discovery', $job->queue);
    }

    public function test_handle_skips_when_article_processing_disabled(): void
    {
        // Arrange
        Setting::create(['key' => 'article_processing_enabled', 'value' => '0']);

        // Mock LogSaver
        $logSaverMock = Mockery::mock(LogSaver::class);
        $logSaverMock->shouldReceive('info')
            ->once()
            ->with('Article processing is disabled. Article discovery skipped.');

        $job = new ArticleDiscoveryJob;

        // Act
        $job->handle($logSaverMock);

        // Assert
        Queue::assertNothingPushed();
    }

    public function test_handle_dispatches_jobs_when_article_processing_enabled(): void
    {
        // Arrange
        Setting::create(['key' => 'article_processing_enabled', 'value' => '1']);

        // Mock LogSaver
        $logSaverMock = Mockery::mock(LogSaver::class);
        $logSaverMock->shouldReceive('info')
            ->with('Starting article discovery for all active feeds')
            ->once();
        $logSaverMock->shouldReceive('info')
            ->with('Article discovery jobs dispatched for all active feeds')
            ->once();

        $job = new ArticleDiscoveryJob;

        // Act
        $job->handle($logSaverMock);

        // Assert - This will test that the static method is called, but we can't easily verify
        // the job dispatch without mocking the static method
        $this->assertTrue(true); // Job completes without error
    }

    public function test_handle_with_default_article_processing_enabled(): void
    {
        // Arrange - No setting exists, should default to enabled
        // Mock LogSaver
        $logSaverMock = Mockery::mock(LogSaver::class);
        $logSaverMock->shouldReceive('info')
            ->with('Starting article discovery for all active feeds')
            ->once();
        $logSaverMock->shouldReceive('info')
            ->with('Article discovery jobs dispatched for all active feeds')
            ->once();

        $job = new ArticleDiscoveryJob;

        // Act
        $job->handle($logSaverMock);

        // Assert - Should complete without skipping
        $this->assertTrue(true); // Job completes without error
    }

    public function test_job_implements_should_queue(): void
    {
        // Arrange
        $job = new ArticleDiscoveryJob;

        // Assert
        $this->assertInstanceOf(ShouldQueue::class, $job);
    }

    public function test_job_uses_queueable_trait(): void
    {
        // Arrange
        $job = new ArticleDiscoveryJob;

        // Assert
        $this->assertTrue(method_exists($job, 'onQueue'));
        $this->assertTrue(method_exists($job, 'onConnection'));
        $this->assertTrue(method_exists($job, 'delay'));
    }

    public function test_handle_logs_appropriate_messages(): void
    {
        // This test verifies that the job calls the logging methods
        // The actual logging is tested in the LogSaver tests

        // Arrange
        // Mock LogSaver
        $logSaverMock = Mockery::mock(LogSaver::class);
        $logSaverMock->shouldReceive('info')
            ->with('Starting article discovery for all active feeds')
            ->once();
        $logSaverMock->shouldReceive('info')
            ->with('Article discovery jobs dispatched for all active feeds')
            ->once();

        $job = new ArticleDiscoveryJob;

        // Act - Should not throw any exceptions
        $job->handle($logSaverMock);

        // Assert - Job completes successfully
        $this->assertTrue(true);
    }

    protected function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }
}
