<?php

namespace Tests\Feature;

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

class RangeDoisControllerTest 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_range_dois_index_page()
    {
        $this->actingAs($this->user);

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

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

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

        RangeDoi::create([
            'name' => 'Critical',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'description' => 'Critical stock level',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('range_dois.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_range_dois_via_ajax()
    {
        $this->actingAs($this->user);

        RangeDoi::create([
            'name' => 'Critical',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'is_active' => true,
            'delete_flag' => false
        ]);

        RangeDoi::create([
            'name' => 'Normal',
            'min_days' => 3.1,
            'max_days' => 7,
            'color_code' => '#28a745',
            'is_active' => true,
            'delete_flag' => false
        ]);

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

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

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

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

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

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

        $rangeDoiData = [
            'name' => 'Critical',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'description' => 'Critical stock level requiring immediate attention',
            'is_active' => true
        ];

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

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

        $this->assertDatabaseHas('m_range_dois', [
            'name' => 'Critical',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'is_active' => true,
            'delete_flag' => false
        ]);
    }

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

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

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

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

        $response = $this->json('POST', route('range_dois.store'), [
            'name' => 'Test Range',
            'min_days' => 'invalid',
            'max_days' => 5,
            'color_code' => '#007bff'
        ]);

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

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

        $response = $this->json('POST', route('range_dois.store'), [
            'name' => 'Test Range',
            'min_days' => 5,
            'max_days' => 3,
            'color_code' => '#007bff'
        ]);

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

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

        $response = $this->json('POST', route('range_dois.store'), [
            'name' => 'Test Range',
            'min_days' => 0,
            'max_days' => 5,
            'color_code' => 'invalid-color'
        ]);

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

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

        $rangeDoi = RangeDoi::create([
            'name' => 'Test Range',
            'min_days' => 0,
            'max_days' => 5,
            'color_code' => '#007bff',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->get(route('range_dois.edit', $rangeDoi));

        $response->assertStatus(200);
        $response->assertViewIs('m-range-dois.form');
        $response->assertViewHas('data', $rangeDoi);
    }

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

        $rangeDoi = RangeDoi::create([
            'name' => 'Original Range',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $updateData = [
            'name' => 'Updated Range',
            'min_days' => 0,
            'max_days' => 5,
            'color_code' => '#28a745',
            'description' => 'Updated description',
            'is_active' => false
        ];

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

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

        $rangeDoi->refresh();
        $this->assertEquals('Updated Range', $rangeDoi->name);
        $this->assertEquals(5, $rangeDoi->max_days);
        $this->assertEquals('#28a745', $rangeDoi->color_code);
        $this->assertFalse($rangeDoi->is_active);
    }

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

        $rangeDoi = RangeDoi::create([
            'name' => 'Critical',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'description' => 'Critical stock level',
            'is_active' => true,
            'delete_flag' => false,
            'created_by' => $this->user->id
        ]);

        $response = $this->get(route('range_dois.show', $rangeDoi));

        $response->assertStatus(200);
        $response->assertViewIs('m-range-dois.show');
        $response->assertViewHas('data', $rangeDoi);
    }

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

        $rangeDoi = RangeDoi::create([
            'name' => 'Test Range',
            'min_days' => 0,
            'max_days' => 5,
            'color_code' => '#007bff',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->delete(route('range_dois.destroy', $rangeDoi));

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

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

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

        RangeDoi::create([
            'name' => 'Critical',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'is_active' => true,
            'delete_flag' => false
        ]);

        RangeDoi::create([
            'name' => 'Normal',
            'min_days' => 3.1,
            'max_days' => 7,
            'color_code' => '#28a745',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('range_dois.check'), [
            'doi_value' => 2
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'doi_value' => 2,
            'category' => 'Critical',
            'color' => '#dc3545'
        ]);
    }

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

        $response = $this->json('GET', route('range_dois.check'));

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

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

        RangeDoi::create([
            'name' => 'Critical',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('range_dois.check'), [
            'doi_value' => 10
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'doi_value' => 10,
            'category' => 'Unknown',
            'color' => '#6c757d'
        ]);
    }

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

        RangeDoi::create([
            'name' => 'Active Range',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'is_active' => true,
            'delete_flag' => false
        ]);

        RangeDoi::create([
            'name' => 'Inactive Range',
            'min_days' => 3.1,
            'max_days' => 7,
            'color_code' => '#28a745',
            'is_active' => false,
            'delete_flag' => false
        ]);

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

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'ranges' => [
                '*' => ['id', 'name', 'min_days', 'max_days', 'color_code', 'range_display']
            ]
        ]);

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

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

        // Create first range
        RangeDoi::create([
            'name' => 'Critical',
            'min_days' => 0,
            'max_days' => 3,
            'color_code' => '#dc3545',
            'is_active' => true,
            'delete_flag' => false
        ]);

        // Try to create overlapping range
        $response = $this->json('POST', route('range_dois.store'), [
            'name' => 'Overlapping Range',
            'min_days' => 2,
            'max_days' => 5,
            'color_code' => '#28a745',
            'is_active' => true
        ]);

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