<?php

namespace Tests\Unit\Models;

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

class ItemConversionTest extends TestCase
{
    use RefreshDatabase;

    protected $testUser;
    protected $testRawMaterial;
    protected $testPeriod;

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

        // Create test period
        $this->testPeriod = Period::create([
            'code' => 'DAILY',
            'name' => 'Daily Period',
            'description' => 'Daily ordering period',
            'is_active' => true,
            'delete_flag' => false
        ]);

        // Create test raw material
        $this->testRawMaterial = RawMaterial::create([
            'code' => 'RM000001',
            'name' => 'Test Raw Material',
            'uom' => 'KG',
            'category' => 'Test Category',
            'konversi_satuan_utuh' => 'DUS',
            'konversi_satuan_pakai' => 'LT',
            'konversi_satuan_kirim' => 'PACK',
            'period_id' => $this->testPeriod->id,
            'lsm_flag' => true,
            'spb_flag' => true,
            'tipe_barang' => 'Kering',
            'delete_flag' => false
        ]);
    }

    /** @test */
    public function it_can_create_item_conversion()
    {
        $conversion = ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'DUS',
            'uom_pakai' => 'LT',
            'conversion_factor' => 3.0000,
            'notes' => 'Test conversion',
            'is_active' => true,
            'created_by' => $this->testUser->id,
            'delete_flag' => false
        ]);

        $this->assertDatabaseHas('m_item_conversions', [
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'DUS',
            'uom_pakai' => 'LT',
            'conversion_factor' => 3.0000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        $this->assertEquals(3.0000, $conversion->conversion_factor);
        $this->assertTrue($conversion->is_active);
    }

    /** @test */
    public function it_has_correct_relationships()
    {
        $conversion = ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'DUS',
            'uom_pakai' => 'LT',
            'conversion_factor' => 3.0000,
            'created_by' => $this->testUser->id,
            'updated_by' => $this->testUser->id,
            'delete_flag' => false
        ]);

        // Test relationships
        $this->assertInstanceOf(RawMaterial::class, $conversion->rawMaterial);
        $this->assertEquals($this->testRawMaterial->id, $conversion->rawMaterial->id);

        $this->assertInstanceOf(User::class, $conversion->creator);
        $this->assertEquals($this->testUser->id, $conversion->creator->id);

        $this->assertInstanceOf(User::class, $conversion->modificator);
        $this->assertEquals($this->testUser->id, $conversion->modificator->id);
    }

    /** @test */
    public function it_can_convert_utuh_to_pakai()
    {
        $conversion = ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'DUS',
            'uom_pakai' => 'LT',
            'conversion_factor' => 3.0000,
            'delete_flag' => false
        ]);

        $result = $conversion->convertUtuhToPakai(2);
        $this->assertEquals(6.0, $result);

        $result = $conversion->convertUtuhToPakai(1.5);
        $this->assertEquals(4.5, $result);
    }

    /** @test */
    public function it_can_convert_pakai_to_utuh()
    {
        $conversion = ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'DUS',
            'uom_pakai' => 'LT',
            'conversion_factor' => 3.0000,
            'delete_flag' => false
        ]);

        $result = $conversion->convertPakaiToUtuh(6);
        $this->assertEquals(2.0, $result);

        $result = $conversion->convertPakaiToUtuh(4.5);
        $this->assertEquals(1.5, $result);
    }

    /** @test */
    public function it_handles_zero_conversion_factor_safely()
    {
        $conversion = ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'DUS',
            'uom_pakai' => 'LT',
            'conversion_factor' => 0,
            'delete_flag' => false
        ]);

        $result = $conversion->convertPakaiToUtuh(6);
        $this->assertEquals(0, $result);
    }

    /** @test */
    public function it_generates_conversion_display_attribute()
    {
        $conversion = ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'DUS',
            'uom_pakai' => 'LT',
            'conversion_factor' => 3.0000,
            'delete_flag' => false
        ]);

        $expected = "1 DUS = 3 LT";
        $this->assertEquals($expected, $conversion->conversion_display);
    }

    /** @test */
    public function it_can_scope_active_conversions()
    {
        // Create active conversion
        ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'DUS',
            'uom_pakai' => 'LT',
            'conversion_factor' => 3.0000,
            'is_active' => true,
            'delete_flag' => false
        ]);

        // Create inactive conversion
        ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'BOX',
            'uom_pakai' => 'KG',
            'conversion_factor' => 2.0000,
            'is_active' => false,
            'delete_flag' => false
        ]);

        // Create deleted conversion
        ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'PACK',
            'uom_pakai' => 'PCS',
            'conversion_factor' => 5.0000,
            'is_active' => true,
            'delete_flag' => true
        ]);

        $activeConversions = ItemConversion::active()->get();
        $this->assertCount(1, $activeConversions);
        $this->assertEquals('DUS', $activeConversions->first()->uom_utuh);
    }

    /** @test */
    public function it_casts_attributes_correctly()
    {
        $conversion = ItemConversion::create([
            'raw_material_id' => $this->testRawMaterial->id,
            'uom_utuh' => 'DUS',
            'uom_pakai' => 'LT',
            'conversion_factor' => '3.1234',
            'is_active' => '1',
            'delete_flag' => '0'
        ]);

        $this->assertIsFloat($conversion->conversion_factor);
        $this->assertEquals(3.1234, $conversion->conversion_factor);
        $this->assertIsBool($conversion->is_active);
        $this->assertTrue($conversion->is_active);
        $this->assertIsBool($conversion->delete_flag);
        $this->assertFalse($conversion->delete_flag);
    }

    /** @test */
    public function it_validates_fillable_attributes()
    {
        $conversion = new ItemConversion();
        $fillable = $conversion->getFillable();

        $expectedFillable = [
            'raw_material_id',
            'uom_utuh',
            'uom_pakai',
            'conversion_factor',
            'notes',
            'is_active',
            'delete_flag',
            'created_by',
            'updated_by',
            'created_at',
            'updated_at',
        ];

        foreach ($expectedFillable as $field) {
            $this->assertContains($field, $fillable);
        }
    }
}