<?php

namespace Tests\Feature;

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

class ItemConversionsControllerTest extends TestCase
{
    use RefreshDatabase;

    protected $user;
    protected $rawMaterial;

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

        $this->rawMaterial = RawMaterial::create([
            'code' => 'RM001',
            'name' => 'Test Raw Material',
            'unit_pakai' => 'LT',
            'unit_utuh' => 'DUS',
            'unit_kirim' => 'DUS',
            'konversi_satuan_utuh' => 'DUS',
            'konversi_satuan_pakai' => 'LT',
            'konversi_satuan_kirim' => 'DUS',
            'is_active' => true,
            'delete_flag' => false
        ]);
    }

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

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

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

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

        ItemConversion::create([
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'is_active' => true,
            'delete_flag' => false
        ]);

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

        ItemConversion::create([
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'is_active' => true,
            'delete_flag' => false
        ]);

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

        $response->assertStatus(200);
        $data = $response->json('data');
        $this->assertGreaterThanOrEqual(1, count($data));
    }

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

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

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

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

        $conversionData = [
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'description' => '1 DUS = 3 LT',
            'is_active' => true
        ];

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

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

        $this->assertDatabaseHas('m_item_conversions', [
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'is_active' => true,
            'delete_flag' => false
        ]);
    }

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

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

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['raw_material_id', 'from_unit', 'to_unit', 'conversion_factor']);
    }

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

        $response = $this->json('POST', route('item_conversions.store'), [
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 'invalid'
        ]);

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

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

        $response = $this->json('POST', route('item_conversions.store'), [
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => -1
        ]);

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

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

        $itemConversion = ItemConversion::create([
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->get(route('item_conversions.edit', $itemConversion));

        $response->assertStatus(200);
        $response->assertViewIs('m-item-conversions.form');
        $response->assertViewHas('data', $itemConversion);
    }

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

        $itemConversion = ItemConversion::create([
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $updateData = [
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 4,
            'description' => '1 DUS = 4 LT (updated)',
            'is_active' => false
        ];

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

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

        $itemConversion->refresh();
        $this->assertEquals(4, $itemConversion->conversion_factor);
        $this->assertEquals('1 DUS = 4 LT (updated)', $itemConversion->description);
        $this->assertFalse($itemConversion->is_active);
    }

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

        $itemConversion = ItemConversion::create([
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'description' => '1 DUS = 3 LT',
            'is_active' => true,
            'delete_flag' => false,
            'created_by' => $this->user->id
        ]);

        $response = $this->get(route('item_conversions.show', $itemConversion));

        $response->assertStatus(200);
        $response->assertViewIs('m-item-conversions.show');
        $response->assertViewHas('data', $itemConversion);
    }

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

        $itemConversion = ItemConversion::create([
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->delete(route('item_conversions.destroy', $itemConversion));

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

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

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

        $response = $this->json('GET', route('item_conversions.preview'), [
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'preview' => '1 DUS = 3 LT'
        ]);
    }

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

        $response = $this->json('GET', route('item_conversions.preview'), [
            'from_unit' => 'DUS'
            // Missing to_unit and conversion_factor
        ]);

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

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

        ItemConversion::create([
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'is_active' => true,
            'delete_flag' => false
        ]);

        ItemConversion::create([
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'LT',
            'to_unit' => 'ML',
            'conversion_factor' => 1000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $response = $this->json('GET', route('item_conversions.by_material'), [
            'raw_material_id' => $this->rawMaterial->id
        ]);

        $response->assertStatus(200);
        $response->assertJsonStructure([
            'raw_material',
            'conversions' => [
                '*' => ['id', 'from_unit', 'to_unit', 'conversion_factor', 'description']
            ]
        ]);

        $conversions = $response->json('conversions');
        $this->assertCount(2, $conversions);
    }

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

        $response = $this->json('GET', route('item_conversions.by_material'));

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

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

        // Create first conversion
        ItemConversion::create([
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 3,
            'is_active' => true,
            'delete_flag' => false
        ]);

        // Try to create duplicate
        $response = $this->json('POST', route('item_conversions.store'), [
            'raw_material_id' => $this->rawMaterial->id,
            'from_unit' => 'DUS',
            'to_unit' => 'LT',
            'conversion_factor' => 4,
            'is_active' => true
        ]);

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