<?php

namespace Tests\Feature;

use Tests\TestCase;
use App\Models\ReasonAdjustment;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ReasonAdjustmentsControllerTest extends TestCase
{
    use RefreshDatabase;

    protected $user;

    protected function setUp(): void
    {
        parent::setUp();
        
        $this->user = User::create([
            'name' => 'Test User',
            'email' => 'test@example.com',
            'password' => bcrypt('password'),
        ]);
    }

    /** @test */
    public function it_can_display_reason_adjustments_index_page()
    {
        $this->actingAs($this->user);

        $response = $this->get(route('reason_adjustments.index'));

        $response->assertStatus(200);
        $response->assertViewIs('m-reason-adjustments.index');
        $response->assertViewHas('variables');
    }

    /** @test */
    public function it_can_get_reason_adjustments_data_via_ajax()
    {
        $this->actingAs($this->user);

        ReasonAdjustment::create([
            'name' => 'Big Order',
            'description' => 'Adjustment due to big order from customer',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('reason_adjustments.index'), [
            'draw' => 1,
            'start' => 0,
            'length' => 10,
            'search' => ['value' => ''],
            'order' => [['column' => 1, 'dir' => 'asc']]
        ], [
            'X-Requested-With' => 'XMLHttpRequest'
        ]);

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'draw',
            'recordsTotal',
            'recordsFiltered',
            'data'
        ]);
    }

    /** @test */
    public function it_can_search_reason_adjustments_via_ajax()
    {
        $this->actingAs($this->user);

        ReasonAdjustment::create([
            'name' => 'Big Order',
            'description' => 'Adjustment due to big order',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        ReasonAdjustment::create([
            'name' => 'Forecast Issue',
            'description' => 'Adjustment due to forecast issue',
            'category' => 'Negative',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('reason_adjustments.index'), [
            'draw' => 1,
            'start' => 0,
            'length' => 10,
            'search' => ['value' => 'Big Order'],
            'order' => [['column' => 1, 'dir' => 'asc']]
        ], [
            'X-Requested-With' => 'XMLHttpRequest'
        ]);

        $response->assertStatus(200);
        $data = $response->json('data');
        $this->assertCount(1, $data);
        $this->assertStringContainsString('Big Order', $data[0][1]);
    }

    /** @test */
    public function it_can_filter_reason_adjustments_by_category()
    {
        $this->actingAs($this->user);

        ReasonAdjustment::create([
            'name' => 'Big Order',
            'description' => 'Positive adjustment',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        ReasonAdjustment::create([
            'name' => 'Forecast Issue',
            'description' => 'Negative adjustment',
            'category' => 'Negative',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('reason_adjustments.index'), [
            'draw' => 1,
            'start' => 0,
            'length' => 10,
            'category' => 'Positive',
            'search' => ['value' => ''],
            'order' => [['column' => 1, 'dir' => 'asc']]
        ], [
            'X-Requested-With' => 'XMLHttpRequest'
        ]);

        $response->assertStatus(200);
        $data = $response->json('data');
        $this->assertCount(1, $data);
        $this->assertStringContainsString('Big Order', $data[0][1]);
    }

    /** @test */
    public function it_can_display_create_reason_adjustment_form()
    {
        $this->actingAs($this->user);

        $response = $this->get(route('reason_adjustments.create'));

        $response->assertStatus(200);
        $response->assertViewIs('m-reason-adjustments.form');
        $response->assertViewHas('data');
        $response->assertViewHas('variables');
    }

    /** @test */
    public function it_can_create_new_reason_adjustment()
    {
        $this->actingAs($this->user);

        $reasonData = [
            'name' => 'Big Order',
            'description' => 'Adjustment due to big order from customer requiring extra stock',
            'category' => 'Positive',
            'is_active' => true
        ];

        $response = $this->json('POST', route('reason_adjustments.store'), $reasonData);

        $response->assertStatus(200);
        $response->assertJson(['success']);

        $this->assertDatabaseHas('m_reason_adjustments', [
            'name' => 'Big Order',
            'description' => 'Adjustment due to big order from customer requiring extra stock',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);
    }

    /** @test */
    public function it_validates_required_fields_when_creating_reason_adjustment()
    {
        $this->actingAs($this->user);

        $response = $this->json('POST', route('reason_adjustments.store'), []);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['name', 'category']);
    }

    /** @test */
    public function it_validates_category_enum_values()
    {
        $this->actingAs($this->user);

        $response = $this->json('POST', route('reason_adjustments.store'), [
            'name' => 'Test Reason',
            'category' => 'InvalidCategory',
            'description' => 'Test description'
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['category']);
    }

    /** @test */
    public function it_can_create_predefined_reason_adjustments()
    {
        $this->actingAs($this->user);

        $predefinedReasons = [
            [
                'name' => 'Big Order',
                'description' => 'Adjustment due to big order from customer',
                'category' => 'Positive'
            ],
            [
                'name' => 'GM Day',
                'description' => 'Adjustment for GM Day special event',
                'category' => 'Neutral'
            ],
            [
                'name' => 'Forecast Issue',
                'description' => 'Adjustment due to forecast calculation issue',
                'category' => 'Negative'
            ]
        ];

        foreach ($predefinedReasons as $reasonData) {
            $reasonData['is_active'] = true;
            
            $response = $this->json('POST', route('reason_adjustments.store'), $reasonData);
            
            $response->assertStatus(200);
            $this->assertDatabaseHas('m_reason_adjustments', [
                'name' => $reasonData['name'],
                'category' => $reasonData['category'],
                'delete_flag' => false
            ]);
        }
    }

    /** @test */
    public function it_can_display_edit_reason_adjustment_form()
    {
        $this->actingAs($this->user);

        $reasonAdjustment = ReasonAdjustment::create([
            'name' => 'Test Reason',
            'description' => 'Test description',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->get(route('reason_adjustments.edit', $reasonAdjustment));

        $response->assertStatus(200);
        $response->assertViewIs('m-reason-adjustments.form');
        $response->assertViewHas('data', $reasonAdjustment);
    }

    /** @test */
    public function it_can_update_existing_reason_adjustment()
    {
        $this->actingAs($this->user);

        $reasonAdjustment = ReasonAdjustment::create([
            'name' => 'Original Reason',
            'description' => 'Original description',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $updateData = [
            'name' => 'Updated Reason',
            'description' => 'Updated description with more details',
            'category' => 'Negative',
            'is_active' => false
        ];

        $response = $this->json('POST', route('reason_adjustments.store', $reasonAdjustment->id), $updateData);

        $response->assertStatus(200);
        $response->assertJson(['success']);

        $reasonAdjustment->refresh();
        $this->assertEquals('Updated Reason', $reasonAdjustment->name);
        $this->assertEquals('Updated description with more details', $reasonAdjustment->description);
        $this->assertEquals('Negative', $reasonAdjustment->category);
        $this->assertFalse($reasonAdjustment->is_active);
    }

    /** @test */
    public function it_can_display_reason_adjustment_details()
    {
        $this->actingAs($this->user);

        $reasonAdjustment = ReasonAdjustment::create([
            'name' => 'Big Order',
            'description' => 'Adjustment due to big order from customer',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false,
            'created_by' => $this->user->id
        ]);

        $response = $this->get(route('reason_adjustments.show', $reasonAdjustment));

        $response->assertStatus(200);
        $response->assertViewIs('m-reason-adjustments.show');
        $response->assertViewHas('data', $reasonAdjustment);
    }

    /** @test */
    public function it_can_delete_reason_adjustment()
    {
        $this->actingAs($this->user);

        $reasonAdjustment = ReasonAdjustment::create([
            'name' => 'Test Reason',
            'description' => 'Test description',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->delete(route('reason_adjustments.destroy', $reasonAdjustment));

        $response->assertRedirect(route('reason_adjustments.index'));
        $response->assertSessionHas('success');

        $reasonAdjustment->refresh();
        $this->assertTrue($reasonAdjustment->delete_flag);
    }

    /** @test */
    public function it_can_get_reasons_by_category()
    {
        $this->actingAs($this->user);

        ReasonAdjustment::create([
            'name' => 'Big Order',
            'description' => 'Positive adjustment',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        ReasonAdjustment::create([
            'name' => 'Extra Stock',
            'description' => 'Another positive adjustment',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        ReasonAdjustment::create([
            'name' => 'Forecast Issue',
            'description' => 'Negative adjustment',
            'category' => 'Negative',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('reason_adjustments.by_category'), [
            'category' => 'Positive'
        ]);

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'category',
            'reasons' => [
                '*' => ['id', 'code', 'name', 'description', 'category']
            ]
        ]);

        $reasons = $response->json('reasons');
        $this->assertCount(2, $reasons);
        $this->assertEquals('Positive', $response->json('category'));
    }

    /** @test */
    public function it_validates_category_parameter_for_by_category_endpoint()
    {
        $this->actingAs($this->user);

        $response = $this->json('GET', route('reason_adjustments.by_category'));

        $response->assertStatus(400);
        $response->assertJson(['error' => 'category parameter required']);
    }

    /** @test */
    public function it_can_get_active_reasons_only()
    {
        $this->actingAs($this->user);

        ReasonAdjustment::create([
            'name' => 'Active Reason',
            'description' => 'Active reason description',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        ReasonAdjustment::create([
            'name' => 'Inactive Reason',
            'description' => 'Inactive reason description',
            'category' => 'Negative',
            'is_active' => false,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('reason_adjustments.active'));

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'reasons' => [
                '*' => ['id', 'code', 'name', 'description', 'category', 'category_badge']
            ]
        ]);

        $reasons = $response->json('reasons');
        $this->assertCount(1, $reasons);
        $this->assertEquals('Active Reason', $reasons[0]['name']);
    }

    /** @test */
    public function it_prevents_duplicate_reason_names()
    {
        $this->actingAs($this->user);

        ReasonAdjustment::create([
            'name' => 'Big Order',
            'description' => 'Existing reason',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('POST', route('reason_adjustments.store'), [
            'name' => 'Big Order',
            'description' => 'Duplicate reason',
            'category' => 'Negative',
            'is_active' => true
        ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['name']);
    }

    /** @test */
    public function it_can_get_all_categories()
    {
        $this->actingAs($this->user);

        $response = $this->json('GET', route('reason_adjustments.categories'));

        $response->assertStatus(200);
        $response->assertJson([
            'categories' => [
                'Positive',
                'Negative',
                'Neutral'
            ]
        ]);
    }

    /** @test */
    public function it_shows_category_badge_in_response()
    {
        $this->actingAs($this->user);

        ReasonAdjustment::create([
            'name' => 'Big Order',
            'description' => 'Positive adjustment',
            'category' => 'Positive',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('reason_adjustments.active'));

        $response->assertStatus(200);
        $reasons = $response->json('reasons');
        $this->assertStringContainsString('badge-success', $reasons[0]['category_badge']);
        $this->assertStringContainsString('Positive', $reasons[0]['category_badge']);
    }
}