<?php

namespace Modules\Lpj\Tests\Jobs;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Jobs\CleanupInspeksiDataJob;
use Modules\Lpj\Models\Inspeksi;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\DokumenJaminan;
use Tests\TestCase;

/**
 * Unit test untuk CleanupInspeksiDataJob
 */
class CleanupInspeksiDataJobTest extends TestCase
{
    use RefreshDatabase;

    protected $permohonan;
    protected $dokumenJaminan;
    protected $userId = 1;

    protected function setUp(): void
    {
        parent::setUp();
        
        // Setup data test
        $this->permohonan = Permohonan::factory()->create();
        $this->dokumenJaminan = DokumenJaminan::factory()->create([
            'permohonan_id' => $this->permohonan->id
        ]);
    }

    /**
     * Test cleanup berhasil menghapus data lama tanpa dokument_id
     */
    public function test_cleanup_successfully_deletes_old_data_without_dokument_id()
    {
        // Buat data lama tanpa dokument_id
        $oldInspeksi1 = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => null,
            'created_by' => $this->userId,
            'deleted_at' => null
        ]);

        $oldInspeksi2 = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => null,
            'created_by' => $this->userId,
            'deleted_at' => null
        ]);

        // Buat data baru dengan dokument_id
        $newInspeksi = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => $this->dokumenJaminan->id,
            'created_by' => $this->userId,
            'deleted_at' => null
        ]);

        // Pastikan data awal ada
        $this->assertDatabaseHas('inspeksi', [
            'id' => $oldInspeksi1->id,
            'deleted_at' => null
        ]);
        $this->assertDatabaseHas('inspeksi', [
            'id' => $oldInspeksi2->id,
            'deleted_at' => null
        ]);
        $this->assertDatabaseHas('inspeksi', [
            'id' => $newInspeksi->id,
            'deleted_at' => null
        ]);

        // Jalankan job
        $job = new CleanupInspeksiDataJob(
            $this->permohonan->id,
            $this->userId,
            $this->dokumenJaminan->id
        );
        $job->handle();

        // Cek hasil: data lama harus soft deleted
        $this->assertSoftDeleted('inspeksi', [
            'id' => $oldInspeksi1->id
        ]);
        $this->assertSoftDeleted('inspeksi', [
            'id' => $oldInspeksi2->id
        ]);
        
        // Data baru tetap ada
        $this->assertDatabaseHas('inspeksi', [
            'id' => $newInspeksi->id,
            'deleted_at' => null
        ]);
    }

    /**
     * Test cleanup tidak menghapus data jika tidak ada data baru dengan dokument_id
     */
    public function test_cleanup_does_not_delete_if_no_new_data_with_dokument_id()
    {
        // Buat data lama tanpa dokument_id
        $oldInspeksi = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => null,
            'created_by' => $this->userId,
            'deleted_at' => null
        ]);

        // Jangan buat data baru dengan dokument_id

        // Jalankan job
        $job = new CleanupInspeksiDataJob(
            $this->permohonan->id,
            $this->userId,
            null
        );
        $job->handle();

        // Data lama tetap ada (tidak dihapus)
        $this->assertDatabaseHas('inspeksi', [
            'id' => $oldInspeksi->id,
            'deleted_at' => null
        ]);
    }

    /**
     * Test cleanup tidak menghapus data dengan created_by berbeda
     */
    public function test_cleanup_does_not_delete_data_with_different_created_by()
    {
        $otherUserId = 2;

        // Buat data lama dengan created_by berbeda
        $oldInspeksi = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => null,
            'created_by' => $otherUserId, // User berbeda
            'deleted_at' => null
        ]);

        // Buat data baru dengan created_by yang sama dengan job
        $newInspeksi = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => $this->dokumenJaminan->id,
            'created_by' => $this->userId, // User sama dengan job
            'deleted_at' => null
        ]);

        // Jalankan job
        $job = new CleanupInspeksiDataJob(
            $this->permohonan->id,
            $this->userId,
            $this->dokumenJaminan->id
        );
        $job->handle();

        // Data lama dengan created_by berbeda tetap ada
        $this->assertDatabaseHas('inspeksi', [
            'id' => $oldInspeksi->id,
            'deleted_at' => null
        ]);

        // Data baru tetap ada
        $this->assertDatabaseHas('inspeksi', [
            'id' => $newInspeksi->id,
            'deleted_at' => null
        ]);
    }

    /**
     * Test cleanup tidak menghapus data yang sudah di-soft delete
     */
    public function test_cleanup_does_not_delete_already_soft_deleted_data()
    {
        // Buat data lama yang sudah di-soft delete
        $oldInspeksi = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => null,
            'created_by' => $this->userId,
            'deleted_at' => now() // Sudah di-soft delete
        ]);

        // Buat data baru dengan dokument_id
        $newInspeksi = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => $this->dokumenJaminan->id,
            'created_by' => $this->userId,
            'deleted_at' => null
        ]);

        // Jalankan job
        $job = new CleanupInspeksiDataJob(
            $this->permohonan->id,
            $this->userId,
            $this->dokumenJaminan->id
        );
        $job->handle();

        // Data lama tetap soft deleted (tidak berubah)
        $this->assertSoftDeleted('inspeksi', [
            'id' => $oldInspeksi->id
        ]);

        // Data baru tetap ada
        $this->assertDatabaseHas('inspeksi', [
            'id' => $newInspeksi->id,
            'deleted_at' => null
        ]);
    }

    /**
     * Test job handle exception properly
     */
    public function test_job_handles_exception_and_rolls_back()
    {
        // Buat data lama tanpa dokument_id
        $oldInspeksi = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => null,
            'created_by' => $this->userId,
            'deleted_at' => null
        ]);

        // Buat data baru dengan dokument_id
        $newInspeksi = Inspeksi::factory()->create([
            'permohonan_id' => $this->permohonan->id,
            'dokument_id' => $this->dokumenJaminan->id,
            'created_by' => $this->userId,
            'deleted_at' => null
        ]);

        // Jalankan job dengan data yang valid
        $job = new CleanupInspeksiDataJob(
            $this->permohonan->id,
            $this->userId,
            $this->dokumenJaminan->id
        );

        // Job seharusnya berhasil dijalankan tanpa exception
        $job->handle();

        // Cek hasil: data lama harus soft deleted
        $this->assertSoftDeleted('inspeksi', [
            'id' => $oldInspeksi->id
        ]);
    }

    /**
     * Test failed method logs error properly
     */
    public function test_failed_method_logs_error()
    {
        // Test bahwa method failed dapat dijalankan tanpa error
        $job = new CleanupInspeksiDataJob(
            $this->permohonan->id,
            $this->userId,
            $this->dokumenJaminan->id
        );

        $exception = new \Exception('Test failure');
        
        // Method failed seharusnya dapat dijalankan
        $job->failed($exception);
        
        // Jika tidak ada exception yang di-throw, test dianggap berhasil
        $this->assertTrue(true);
    }
}