<?php

namespace Tests\Feature;

use App\Models\JobListing;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\Feature\Concerns\BuildsFeatureData;
use Tests\TestCase;

class AdminJobsAndStagesFeatureTest extends TestCase
{
    use BuildsFeatureData;
    use DatabaseTransactions;

    private function loginAsAdmin(): void
    {
        $this->actingAs($this->createAdminUser());
    }

    public function test_admin_can_open_jobs_index_and_create_page(): void
    {
        $this->loginAsAdmin();
        $this->createJob([
            'title' => 'Job Uji Copy',
            'company' => 'PT Uji Copy',
        ]);

        $jobsIndexResponse = $this->get(route('admin.jobs.index'));
        $jobsIndexResponse->assertOk();
        $jobsIndexResponse->assertDontSee('Copy Lowongan Cepat');
        $jobsIndexResponse->assertDontSee('Duplikasi lowongan dengan perusahaan berbeda tanpa input ulang dari nol.');
        $jobsIndexResponse->assertSee('id="copy-job-modal"', false);
        $jobsIndexResponse->assertSee('Nama perusahaan baru');
        $jobsIndexResponse->assertSee('data-copy-job-trigger', false);
        $jobsIndexResponse->assertSee('Lowongan yang akan dicopy tidak valid. Muat ulang halaman lalu coba lagi.');

        $this->get(route('admin.jobs.create'))->assertOk();
    }

    public function test_admin_can_store_job_and_default_stages_are_created(): void
    {
        $this->loginAsAdmin();

        $response = $this->post(route('admin.jobs.store'), [
            'title' => 'Backend Engineer Senior',
            'company' => 'PT Maju Jaya',
            'location' => 'Jakarta',
            'type' => 'Full-time',
            'salary_min' => 10000000,
            'salary_max' => 15000000,
            'requirements' => 'Pengalaman minimal 3 tahun',
            'description' => 'Membangun layanan backend',
            'benefits' => 'BPJS, THR',
            'is_active' => '1',
            'deadline' => now()->addDays(10)->toDateString(),
        ]);

        $job = JobListing::where('title', 'Backend Engineer Senior')->firstOrFail();

        $response->assertRedirect(route('admin.jobs.edit', $job));
        $this->assertDatabaseHas('job_listings', [
            'id' => $job->id,
            'company' => 'PT Maju Jaya',
        ]);
        $this->assertSame(5, $job->stages()->count());
    }

    public function test_admin_can_update_existing_job(): void
    {
        $this->loginAsAdmin();
        $job = $this->createJob([
            'title' => 'Judul Lama',
        ]);

        $response = $this->patch(route('admin.jobs.update', $job), [
            'title' => 'Judul Baru',
            'company' => 'PT Baru',
            'location' => 'Bandung',
            'type' => 'Contract',
            'salary_min' => 5000000,
            'salary_max' => 7000000,
            'requirements' => 'Syarat terbaru',
            'description' => 'Deskripsi terbaru',
            'benefits' => 'Asuransi',
            'is_active' => '1',
            'deadline' => now()->addDays(5)->toDateString(),
        ]);

        $response->assertRedirect(route('admin.jobs.index'));
        $this->assertDatabaseHas('job_listings', [
            'id' => $job->id,
            'title' => 'Judul Baru',
            'company' => 'PT Baru',
            'type' => 'Contract',
        ]);
    }

    public function test_admin_can_copy_job_to_new_company(): void
    {
        $this->loginAsAdmin();

        $job = $this->createJob([
            'title' => 'Lowongan Source',
            'company' => 'PT Source',
        ]);
        $this->createStage($job, ['stage_number' => 1, 'sort_order' => 1]);
        $this->createStage($job, ['stage_number' => 2, 'sort_order' => 2]);

        $response = $this->post(route('admin.jobs.copy', $job), [
            'company' => 'PT Tujuan',
        ]);

        $copiedJob = JobListing::where('title', 'Lowongan Source')
            ->where('company', 'PT Tujuan')
            ->firstOrFail();

        $response->assertRedirect(route('admin.jobs.edit', $copiedJob));
        $this->assertSame(2, $copiedJob->stages()->count());
    }

    public function test_admin_can_delete_job(): void
    {
        $this->loginAsAdmin();
        $job = $this->createJob();

        $response = $this->delete(route('admin.jobs.destroy', $job));

        $response->assertRedirect(route('admin.jobs.index'));
        $this->assertDatabaseMissing('job_listings', ['id' => $job->id]);
    }

    public function test_admin_can_view_edit_update_and_toggle_stage(): void
    {
        $this->loginAsAdmin();

        $job = $this->createJob();
        $stage = $this->createStage($job, [
            'stage_number' => 1,
            'name' => 'Tahap Awal',
            'is_active' => true,
            'sort_order' => 1,
        ]);

        $this->get(route('admin.jobs.stages.index', $job))->assertOk();
        $this->get(route('admin.jobs.stages.edit', [$job, $stage]))->assertOk();

        $response = $this->put(route('admin.jobs.stages.update', [$job, $stage]), [
            'name' => 'Tahap Diperbarui',
            'description' => 'Deskripsi baru',
            'form_fields' => json_encode([
                [
                    'name' => 'pengalaman',
                    'label' => 'Pengalaman',
                    'type' => 'textarea',
                    'required' => true,
                ],
            ], JSON_THROW_ON_ERROR),
            'is_active' => '1',
        ]);

        $response->assertRedirect(route('admin.jobs.stages.index', $job));
        $this->assertDatabaseHas('job_stages', [
            'id' => $stage->id,
            'name' => 'Tahap Diperbarui',
            'is_active' => true,
        ]);

        $toggleResponse = $this->patch(route('admin.jobs.stages.toggle', [$job, $stage]));

        $toggleResponse->assertStatus(302);
        $this->assertDatabaseHas('job_stages', [
            'id' => $stage->id,
            'is_active' => false,
        ]);
    }

    public function test_stage_route_returns_404_for_mismatched_job(): void
    {
        $this->loginAsAdmin();

        $jobA = $this->createJob();
        $jobB = $this->createJob();
        $stageOfA = $this->createStage($jobA, ['stage_number' => 1]);

        $response = $this->get(route('admin.jobs.stages.edit', [$jobB, $stageOfA]));

        $response->assertNotFound();
    }
}
