<?php

namespace Tests\Feature;

use App\Models\User;
use App\Models\QurbanParticipant;
use App\Models\Antrian;
use App\Models\Distribution;
use App\Models\Titip;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;

class QueueDistributionTest extends TestCase
{
    use DatabaseTransactions;

    protected function setUp(): void
    {
        parent::setUp();
        // Force database connection to mysql for testing against the local database in a transaction
        config([
            'database.default' => 'mysql',
            'database.connections.mysql.database' => 'qurban',
        ]);
    }

    public function test_guest_cannot_access_distribution_page()
    {
        $response = $this->get(route('distribution.index'));
        $response->assertRedirect(route('login'));
    }

    public function test_authenticated_user_can_access_distribution_page()
    {
        $user = User::first();
        if (!$user) {
            $user = User::create([
                'name' => 'Test Admin',
                'email' => 'test@admin.com',
                'password' => bcrypt('password'),
            ]);
        }

        $response = $this->actingAs($user)->get(route('distribution.index'));
        $response->assertStatus(200);
        $response->assertViewIs('distribution.index');
        $response->assertSee('Antrean Ambil Daging');
    }

    public function test_scan_coupon_adds_participant_to_queue()
    {
        $user = User::first();
        if (!$user) {
            $user = User::create([
                'name' => 'Test Admin',
                'email' => 'test@admin.com',
                'password' => bcrypt('password'),
            ]);
        }

        // Get a participant that is not in the queue and hasn't received package yet
        $participant = QurbanParticipant::whereDoesntHave('antrian')
            ->whereDoesntHave('distribution', function ($q) {
                $q->where('status', 'Sudah');
            })
            ->first();

        $this->assertNotNull($participant, 'Need at least one eligible participant in DB to test.');

        // Search/Scan coupon via AJAX
        $response = $this->actingAs($user)
            ->get(route('distribution.search-ajax', ['code' => $participant->no_kupon]));

        $response->assertStatus(200);
        $response->assertJson([
            'success' => true,
            'already_queued' => false,
        ]);

        // Check participant is in queue table
        $this->assertTrue(Antrian::where('qurban_participant_id', $participant->id)->exists());

        // Check index page shows participant in queue
        $responseIndex = $this->actingAs($user)->get(route('distribution.index'));
        $responseIndex->assertSee($participant->nama);
        $responseIndex->assertSee($participant->no_kupon);
    }

    public function test_can_distribute_package_from_queue()
    {
        $user = User::first();
        if (!$user) {
            $user = User::create([
                'name' => 'Test Admin',
                'email' => 'test@admin.com',
                'password' => bcrypt('password'),
            ]);
        }

        // Setup a participant in queue
        $participant = QurbanParticipant::whereDoesntHave('distribution')
            ->whereDoesntHave('antrian')
            ->first();
        $this->assertNotNull($participant);

        Antrian::create([
            'qurban_participant_id' => $participant->id,
        ]);

        // Perform distribution
        $response = $this->actingAs($user)
            ->post(route('distribution.distribute', $participant->id));

        $response->assertRedirect();
        
        // Verify participant is removed from queue
        $this->assertFalse(Antrian::where('qurban_participant_id', $participant->id)->exists());

        // Verify distribution status is "Sudah"
        $distribution = Distribution::where('qurban_participant_id', $participant->id)->first();
        $this->assertNotNull($distribution);
        $this->assertEquals('Sudah', $distribution->status);
    }

    public function test_can_cancel_queue_item()
    {
        $user = User::first();
        if (!$user) {
            $user = User::create([
                'name' => 'Test Admin',
                'email' => 'test@admin.com',
                'password' => bcrypt('password'),
            ]);
        }

        // Setup a participant in queue
        $participant = QurbanParticipant::first();
        Antrian::updateOrCreate([
            'qurban_participant_id' => $participant->id,
        ]);

        // Perform cancellation
        $response = $this->actingAs($user)
            ->post(route('distribution.cancel-queue', $participant->id));

        $response->assertRedirect();

        // Verify removed from queue
        $this->assertFalse(Antrian::where('qurban_participant_id', $participant->id)->exists());
    }

    public function test_guest_cannot_access_queue_list_page()
    {
        $response = $this->get(route('distribution.antrian'));
        $response->assertRedirect(route('login'));
    }

    public function test_authenticated_user_can_access_queue_list_page()
    {
        $user = User::first();
        if (!$user) {
            $user = User::create([
                'name' => 'Test Admin',
                'email' => 'test@admin.com',
                'password' => bcrypt('password'),
            ]);
        }

        // Setup a participant in queue who has not yet received their package
        $participant = QurbanParticipant::where(function($query) {
            $query->whereDoesntHave('distribution')
                  ->orWhereHas('distribution', function($q) {
                      $q->where('status', '!=', 'Sudah');
                  });
        })->first();
        $this->assertNotNull($participant);

        Antrian::updateOrCreate([
            'qurban_participant_id' => $participant->id,
        ]);

        $response = $this->actingAs($user)->get(route('distribution.antrian'));
        $response->assertStatus(200);
        $response->assertViewIs('distribution.antrian');
        $response->assertSee('Antrean Aktif');
        $response->assertSee($participant->nama);
    }

    public function test_paket_distribusi_filters_by_status()
    {
        $user = User::first();
        if (!$user) {
            $user = User::create([
                'name' => 'Test Admin',
                'email' => 'test@admin.com',
                'password' => bcrypt('password'),
            ]);
        }

        // Test status=belum filter
        $responseBelum = $this->actingAs($user)->get(route('distribution.paket', ['status' => 'belum']));
        $responseBelum->assertStatus(200);
        $responseBelum->assertViewIs('distribution.paket');

        // Test status=sudah filter
        $responseSudah = $this->actingAs($user)->get(route('distribution.paket', ['status' => 'sudah']));
        $responseSudah->assertStatus(200);
        $responseSudah->assertViewIs('distribution.paket');
    }
}
