<?php

namespace Tests\Feature\Integration;

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

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

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

        if (! moduleExists('SystemCore') || ! moduleExists('WMSInventoryCore')) {
            $this->markTestSkipped('SystemCore and WMSInventoryCore modules are required');
        }
    }

    // ==========================================
    // Product to Inventory Tests
    // ==========================================

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

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

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

        $this->assertEquals($product->id, $inventory->core_product_id);
        $this->assertEquals($warehouse->id, $inventory->warehouse_id);
    }

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

        $product = $this->createCoreProduct(['created_by_id' => $admin->id]);
        $warehouse1 = $this->createWarehouse(['name' => 'Warehouse A', 'created_by_id' => $admin->id]);
        $warehouse2 = $this->createWarehouse(['name' => 'Warehouse B', 'created_by_id' => $admin->id]);
        $warehouse3 = $this->createWarehouse(['name' => 'Warehouse C', 'created_by_id' => $admin->id]);

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

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

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

        // Total stock across all warehouses
        $totalStock = \Modules\WMSInventoryCore\App\Models\Inventory::where('core_product_id', $product->id)
            ->sum('stock_level');

        $this->assertEquals(150, $totalStock);
    }

    // ==========================================
    // Order to Warehouse Tests
    // ==========================================

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

        $warehouse = $this->createMainWarehouse(['created_by_id' => $admin->id]);
        $salesOrder = $this->createCoreSalesOrder([
            'warehouse_id' => $warehouse->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals($warehouse->id, $salesOrder->warehouse_id);
    }

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

        $warehouse = $this->createMainWarehouse(['created_by_id' => $admin->id]);
        $purchaseOrder = $this->createCorePurchaseOrder([
            'warehouse_id' => $warehouse->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals($warehouse->id, $purchaseOrder->warehouse_id);
    }

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

        $warehouse = $this->createMainWarehouse(['created_by_id' => $admin->id]);

        $this->createCoreSalesOrder([
            'warehouse_id' => $warehouse->id,
            'created_by_id' => $admin->id,
        ]);

        $this->createCoreSalesOrder([
            'warehouse_id' => $warehouse->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertCount(2, $warehouse->sales);
    }

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

        $warehouse = $this->createMainWarehouse(['created_by_id' => $admin->id]);

        $this->createCorePurchaseOrder([
            'warehouse_id' => $warehouse->id,
            'created_by_id' => $admin->id,
        ]);

        $this->createCorePurchaseOrder([
            'warehouse_id' => $warehouse->id,
            'created_by_id' => $admin->id,
        ]);

        $this->assertCount(2, $warehouse->purchases);
    }

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

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

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

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

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

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

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

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

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

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

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

    // ==========================================
    // Multi-Warehouse Inventory Tests
    // ==========================================

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

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

        $warehouse1 = $this->createWarehouse(['created_by_id' => $admin->id]);
        $warehouse2 = $this->createWarehouse(['created_by_id' => $admin->id]);

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

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

        $totalStock = \Modules\WMSInventoryCore\App\Models\Inventory::where('core_product_id', $product->id)
            ->sum('stock_level');

        $totalReserved = \Modules\WMSInventoryCore\App\Models\Inventory::where('core_product_id', $product->id)
            ->sum('reserved_quantity');

        $this->assertEquals(150, $totalStock);
        $this->assertEquals(15, $totalReserved);
    }

    // ==========================================
    // Cost Price Tests
    // ==========================================

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

        $product = $this->createCoreProduct([
            'base_price' => 25.00,
            'created_by_id' => $admin->id,
        ]);

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

        $inventory = $this->createInventory([
            'warehouse_id' => $warehouse->id,
            'core_product_id' => $product->id,
            'stock_level' => 100,
            'cost_price' => 20.00, // Purchase cost
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(20.00, $inventory->cost_price);
    }
}
