<?php

namespace Tests\Feature\WMSInventoryCore;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Modules\WMSInventoryCore\App\Models\Warehouse;
use Tests\TestCase;
use Tests\Traits\CreatesSystemCoreEntities;
use Tests\Traits\CreatesUsers;
use Tests\Traits\CreatesWMSInventoryEntities;

class WarehouseTest 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');
        }
    }

    // ==========================================
    // Creation Tests
    // ==========================================

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

        $warehouse = $this->createWarehouse([
            'name' => 'Main Distribution Center',
            'code' => 'WH-MDC-001',
            'created_by_id' => $admin->id,
        ]);

        $this->assertDatabaseHas('warehouses', [
            'name' => 'Main Distribution Center',
            'code' => 'WH-MDC-001',
        ]);
    }

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

        $warehouse = $this->createWarehouse([
            'name' => 'Test Warehouse',
            'code' => 'TW-001',
            'address' => '456 Industrial Park',
            'city' => 'Commerce City',
            'state' => 'Colorado',
            'country' => 'USA',
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('Test Warehouse', $warehouse->name);
        $this->assertEquals('TW-001', $warehouse->code);
        $this->assertEquals('Commerce City', $warehouse->city);
    }

    // ==========================================
    // Main Warehouse Tests
    // ==========================================

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

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

        $this->assertTrue($mainWarehouse->is_main);
    }

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

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

        $firstMain->refresh();

        $this->assertFalse($firstMain->is_main);
        $this->assertTrue($secondMain->is_main);
    }

    // ==========================================
    // Full Address Tests
    // ==========================================

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

        $warehouse = $this->createWarehouse([
            'address' => '123 Main St',
            'city' => 'New York',
            'state' => 'NY',
            'postal_code' => '10001',
            'country' => 'USA',
            'created_by_id' => $admin->id,
        ]);

        $fullAddress = $warehouse->full_address;

        $this->assertStringContainsString('123 Main St', $fullAddress);
        $this->assertStringContainsString('New York', $fullAddress);
        $this->assertStringContainsString('NY', $fullAddress);
        $this->assertStringContainsString('10001', $fullAddress);
        $this->assertStringContainsString('USA', $fullAddress);
    }

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

        $warehouse = $this->createWarehouse([
            'address' => '123 Main St',
            'city' => 'New York',
            'state' => null,
            'postal_code' => null,
            'country' => null,
            'created_by_id' => $admin->id,
        ]);

        $fullAddress = $warehouse->full_address;

        $this->assertStringContainsString('123 Main St', $fullAddress);
        $this->assertStringContainsString('New York', $fullAddress);
    }

    // ==========================================
    // Operating Hours Tests
    // ==========================================

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

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

        $this->assertTrue($warehouse->isCurrentlyOpen());
    }

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

        $warehouse = $this->createWarehouse([
            'is_24_hours' => false,
            'operating_days' => null,
            'created_by_id' => $admin->id,
        ]);

        $this->assertTrue($warehouse->isCurrentlyOpen());
    }

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

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

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

        $this->assertTrue($warehouse->is_active);
    }

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

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

        $this->assertFalse($warehouse->is_active);
    }

    // ==========================================
    // Configuration Tests
    // ==========================================

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

        $allowNegative = $this->createWarehouse([
            'allow_negative_inventory' => true,
            'created_by_id' => $admin->id,
        ]);

        $disallowNegative = $this->createWarehouse([
            'allow_negative_inventory' => false,
            'created_by_id' => $admin->id,
        ]);

        $this->assertTrue($allowNegative->allow_negative_inventory);
        $this->assertFalse($disallowNegative->allow_negative_inventory);
    }

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

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

        $this->assertTrue($warehouse->requires_approval);
    }

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

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

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

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

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

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

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

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

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

        $this->assertCount(3, $warehouse->zones);
    }

    // ==========================================
    // Capacity Tests
    // ==========================================

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

        $warehouse = $this->createWarehouse([
            'storage_capacity' => 10000.00,
            'max_weight_capacity' => 50000.00,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(10000.00, $warehouse->storage_capacity);
        $this->assertEquals(50000.00, $warehouse->max_weight_capacity);
    }

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

        $warehouse = $this->createWarehouse([
            'shelf_count' => 100,
            'rack_count' => 50,
            'bin_count' => 500,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(100, $warehouse->shelf_count);
        $this->assertEquals(50, $warehouse->rack_count);
        $this->assertEquals(500, $warehouse->bin_count);
    }

    // ==========================================
    // Location Tests
    // ==========================================

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

        $warehouse = $this->createWarehouse([
            'latitude' => 40.7128,
            'longitude' => -74.0060,
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals(40.7128, $warehouse->latitude);
        $this->assertEquals(-74.0060, $warehouse->longitude);
    }

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

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

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

        $warehouse->delete();

        $this->assertSoftDeleted('warehouses', ['id' => $warehouseId]);
    }

    // ==========================================
    // Contact Information Tests
    // ==========================================

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

        $warehouse = $this->createWarehouse([
            'contact_person' => 'John Smith',
            'contact_name' => 'John Smith',
            'contact_email' => 'john@warehouse.com',
            'contact_phone' => '+1234567890',
            'phone_number' => '+1234567890',
            'email' => 'warehouse@company.com',
            'created_by_id' => $admin->id,
        ]);

        $this->assertEquals('John Smith', $warehouse->contact_person);
        $this->assertEquals('john@warehouse.com', $warehouse->contact_email);
        $this->assertEquals('+1234567890', $warehouse->contact_phone);
    }
}
