<?php

namespace Tests\Feature\Integration;

use Tests\TestCase;
use App\Modules\Core\Models\Tenant;
use App\Modules\Core\Models\User;
use App\Modules\Inventory\Models\Product;
use App\Modules\Integration\Models\SalesOrder;
use Illuminate\Support\Facades\DB;
use Stancl\Tenancy\Facades\Tenancy;

class PosApiTest extends TestCase
{
    // Use RefreshDatabase to reset DB state. 
    // Note: In Tenancy, this usually resets Central DB. 
    // For Tenant DBs, we heavily rely on Stancl's behavior or need to act carefully.
    // For now, assume we can create a tenant and its DB will be migrated or accessible.
    
    protected $tenant;
    protected $user;
    protected $token;
    protected $domain;

    protected function setUp(): void
    {
        parent::setUp();
        
        \Artisan::call('migrate:fresh'); // Force fresh DB for isolation without RefreshDatabase trait
        
        $this->domain = 'test-' . \Illuminate\Support\Str::random(8) . '.erp.local';
        $tenantId = 'test_tenant_' . \Illuminate\Support\Str::random(8);

        // Ensure we are in central context
        tenancy()->central(function () use ($tenantId) {
             // Create a tenant
            $this->tenant = Tenant::create([
                'id' => $tenantId,
                'name' => 'Test Tenant',
            ]);
            
            $this->tenant->domains()->create(['domain' => $this->domain]);
        });

        // Initialize to create User and Token
        tenancy()->initialize($this->tenant);
        
        \Artisan::call('tenants:migrate');

        $this->user = User::factory()->create([
            'email' => 'admin@test.local',
            'name' => 'Admin',
        ]);
        
        $this->token = $this->user->createToken('POS-Test-Token')->plainTextToken;
        
        $category = \App\Modules\Inventory\Models\Category::create(['name' => 'General', 'code' => 'GEN']);

        // Create a product for testing
        Product::create([
            'name' => 'Existing Product',
            'code' => 'P-001',
            'external_pos_id' => 'EXT-001',
            'sku' => 'SKU-001',
            'price' => 100,
            'is_active' => true,
            'category_id' => $category->id,
        ]);
        
        // End tenancy initialization to simulate external request
        tenancy()->end();
    }

    protected function tearDown(): void
    {
        if ($this->tenant) {
            $this->tenant->delete();
        }
        parent::tearDown();
    }
    
    public function test_upsert_product_creates_new_product()
    {
        \Laravel\Sanctum\Sanctum::actingAs($this->user, ['*']);

        $payload = [
            'external_pos_id' => 'EXT-NEW-002',
            'name' => 'New Product',
            'price' => 200,
            'sku' => 'SKU-NEW',
        ];

        $response = $this->withHeaders([
            'X-Tenant-Domain' => $this->domain,
            'Accept' => 'application/json',
        ])->postJson('/api/v1/integration/products/upsert', $payload);

        $response->assertStatus(200)
                 ->assertJsonPath('message', 'Product synced successfully');

        // Verify in Tenant DB
        tenancy()->initialize($this->tenant);
        $this->assertDatabaseHas('products', [
            'external_pos_id' => 'EXT-NEW-002',
            'name' => 'New Product',
        ]);
        tenancy()->end();
    }

    public function test_upsert_product_updates_existing_product()
    {
        \Laravel\Sanctum\Sanctum::actingAs($this->user, ['*']);

        $payload = [
            'external_pos_id' => 'EXT-001',
            'name' => 'Updated Name',
            'price' => 150,
        ];

        $response = $this->withHeaders([
            'X-Tenant-Domain' => $this->domain,
            'Accept' => 'application/json',
        ])->postJson('/api/v1/integration/products/upsert', $payload);

        $response->assertStatus(200);

        tenancy()->initialize($this->tenant);
        $this->assertDatabaseHas('products', [
            'external_pos_id' => 'EXT-001',
            'name' => 'Updated Name',
            'price' => 150,
        ]);
        tenancy()->end();
    }

    public function test_create_order_deducts_inventory()
    {
        // Setup inventory first
        tenancy()->initialize($this->tenant);
        $product = Product::where('external_pos_id', 'EXT-001')->first();
        
        // We need a warehouse
        $warehouse = \App\Modules\Inventory\Models\Warehouse::create(['name' => 'Main Warehouse', 'code' => 'MAIN']);
        
        // Add initial stock
        \App\Modules\Inventory\Models\Inventory::create([
            'product_id' => $product->id,
            'warehouse_id' => $warehouse->id,
            'quantity' => 100,
            'batch_number' => 'BATCH-TEST-001',
            'arrival_date' => now()->toDateString(),
            'origin_country' => 'TW',
        ]);
        
        $warehouseId = $warehouse->id;
        tenancy()->end();

        \Laravel\Sanctum\Sanctum::actingAs($this->user, ['*']);

        $payload = [
            'external_order_id' => 'ORD-001',
            'warehouse_id' => $warehouseId,
            'sold_at' => now()->toIso8601String(),
            'items' => [
                [
                    'pos_product_id' => 'EXT-001',
                    'qty' => 5,
                    'price' => 100
                ]
            ]
        ];

        $response = $this->withHeaders([
            'X-Tenant-Domain' => $this->domain,
            'Accept' => 'application/json',
        ])->postJson('/api/v1/integration/orders', $payload);

        $response->assertStatus(201)
                 ->assertJsonPath('message', 'Order synced and stock deducted successfully');

        // Verify Order and Inventory
        tenancy()->initialize($this->tenant);
        
        $this->assertDatabaseHas('sales_orders', [
            'external_order_id' => 'ORD-001',
        ]);
        
        $this->assertDatabaseHas('sales_order_items', [
            'product_id' => $product->id, // We need to fetch ID again or rely on correct ID
            'quantity' => 5,
        ]);
        
        // Verify stock deducted: 100 - 5 = 95
        $this->assertDatabaseHas('inventories', [
            'product_id' => $product->id,
            'warehouse_id' => $warehouseId,
            'quantity' => 95,
        ]);
        
        tenancy()->end();
    }
}
