<?php

namespace Tests\Feature\WMSInventoryCore;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use Tests\Traits\CreatesSystemCoreEntities;
use Tests\Traits\CreatesUsers;
use Tests\Traits\CreatesWMSInventoryEntities;

class InventoryTest extends TestCase
{
    use CreatesSystemCoreEntities;
    use CreatesUsers;
    use CreatesWMSInventoryEntities;
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();

        if (! moduleExists('WMSInventoryCore')) {
            $this->markTestSkipped('WMSInventoryCore module is not enabled');
        }
    }

    // ==========================================
    // Stock Level Tests
    // ==========================================

    public function test_inventory_tracks_stock_level(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 150,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(150, $inventory->stock_level);
    }

    public function test_inventory_tracks_reserved_quantity(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 100,
            'reserved_quantity' => 25,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(25, $inventory->reserved_quantity);
    }

    public function test_inventory_tracks_damaged_quantity(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createDamagedInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(30, $inventory->damaged_quantity);
    }

    public function test_inventory_tracks_quarantine_quantity(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createQuarantineInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(25, $inventory->quarantine_quantity);
    }

    public function test_inventory_tracks_in_transit_quantity(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'in_transit_quantity' => 50,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(50, $inventory->in_transit_quantity);
    }

    // ==========================================
    // Health Status Tests
    // ==========================================

    public function test_health_status_low_when_below_min_stock(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct([
            'min_stock_level' => 50,
            'created_by_id' => $admin->id,
        ]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 10,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('low', $inventory->health_status);
    }

    public function test_health_status_overstocked_when_above_max(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct([
            'max_stock_level' => 100,
            'created_by_id' => $admin->id,
        ]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 150,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('overstocked', $inventory->health_status);
    }

    public function test_health_status_reorder_when_below_reorder_point(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct([
            'reorder_level' => 25, // CoreProduct uses reorder_level, not reorder_point
            'min_stock_level' => 10,
            'created_by_id' => $admin->id,
        ]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 20,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('reorder', $inventory->health_status);
    }

    public function test_health_status_healthy_when_in_normal_range(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct([
            'min_stock_level' => 10,
            'max_stock_level' => 100,
            'reorder_level' => 20, // CoreProduct uses reorder_level, not reorder_point
            'created_by_id' => $admin->id,
        ]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 50,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('healthy', $inventory->health_status);
    }

    // ==========================================
    // Quality Status Tests
    // ==========================================

    public function test_quality_status_good_when_no_damaged_or_quarantine(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 100,
            'damaged_quantity' => 0,
            'quarantine_quantity' => 0,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('good', $inventory->quality_status);
    }

    public function test_quality_status_acceptable_when_minor_issues(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 100,
            'damaged_quantity' => 5,
            'quarantine_quantity' => 5,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('acceptable', $inventory->quality_status);
    }

    public function test_quality_status_warning_when_significant_issues(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 100,
            'damaged_quantity' => 15,
            'quarantine_quantity' => 15,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('warning', $inventory->quality_status);
    }

    public function test_quality_status_critical_when_major_issues(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 100,
            'damaged_quantity' => 30,
            'quarantine_quantity' => 30,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('critical', $inventory->quality_status);
    }

    // ==========================================
    // Stock Level Check Tests
    // ==========================================

    public function test_is_below_reorder_point(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct([
            'reorder_level' => 50, // CoreProduct uses reorder_level, not reorder_point
            'created_by_id' => $admin->id,
        ]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 30,
            'created_by_id' => $admin->id,
        ]);

        $this->assertTrue($inventory->isBelowReorderPoint());
    }

    public function test_is_not_below_reorder_point_when_above(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct([
            'reorder_level' => 50, // CoreProduct uses reorder_level, not reorder_point
            'created_by_id' => $admin->id,
        ]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 75,
            'created_by_id' => $admin->id,
        ]);

        $this->assertFalse($inventory->isBelowReorderPoint());
    }

    public function test_is_below_min_stock(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct([
            'min_stock_level' => 20,
            'created_by_id' => $admin->id,
        ]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 10,
            'created_by_id' => $admin->id,
        ]);

        $this->assertTrue($inventory->isBelowMinStock());
    }

    public function test_is_above_max_stock(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct([
            'max_stock_level' => 100,
            'created_by_id' => $admin->id,
        ]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 150,
            'created_by_id' => $admin->id,
        ]);

        $this->assertTrue($inventory->isAboveMaxStock());
    }

    // ==========================================
    // Relationship Tests
    // ==========================================

    public function test_inventory_belongs_to_warehouse(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertNotNull($inventory->warehouse);
        $this->assertEquals($warehouse->id, $inventory->warehouse->id);
    }

    public function test_inventory_belongs_to_product(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertNotNull($inventory->product);
        $this->assertEquals($product->id, $inventory->product->id);
    }

    // ==========================================
    // Soft Delete Tests
    // ==========================================

    public function test_inventory_can_be_soft_deleted(): void
    {
        $admin = $this->createAdmin();
        $this->actingAs($admin);

        $warehouse = $this->createWarehouse(['created_by_id' => $admin->id]);
        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'created_by_id' => $admin->id,
        ]);

        $inventoryId = $inventory->id;
        $inventory->delete();

        $this->assertSoftDeleted('inventories', ['id' => $inventoryId]);
    }
}
