<?php
require_once __DIR__ . '/../bootstrap.php';

use Gestoreasy\Core\Kernel;
use Gestoreasy\Core\Http\Request;
use Gestoreasy\Core\Auth\Jwt;
use Gestoreasy\Core\Tenant\TenantAdmin;
use Gestoreasy\Core\Tenant\ConnectionManager;

function assertTrue($cond, $msg) { if (!$cond) { echo "FAIL: $msg\n"; exit(1); } }

$kernel = new Kernel();
$tenant = 'default';
TenantAdmin::runMigrations($tenant);
$pdo = ConnectionManager::forTenant($tenant);

// Preparar produto e bin
$sku = 'SKU-MOBILE-' . substr((string)mt_rand(1000, 999999), 0, 6);
$stmt = $pdo->prepare('INSERT INTO products (codigo, preco, estoque, created_at) VALUES (?, ?, ?, NOW())');
$stmt->execute([$sku, 9.99, 0]);
$productId = (int)$pdo->lastInsertId();
assertTrue($productId > 0, 'Produto criado deve ter id > 0');

$pdo->exec("INSERT INTO warehouses(name) VALUES('W1')");
$warehouseId = (int)$pdo->lastInsertId();
$binCode = 'A-01-01';
$stmt = $pdo->prepare('INSERT INTO bins (warehouse_id, code, description) VALUES (?, ?, ?)');
$stmt->execute([$warehouseId, $binCode, 'Bin teste']);
$binId = (int)$pdo->lastInsertId();
assertTrue($binId > 0, 'Bin criado deve ter id > 0');

// Preparar headers
$payload = [ 'sub' => 1, 'email' => 'admin@local', 'name' => 'Admin', 'tenant' => $tenant, 'roles' => ['admin'] ];
$token = Jwt::sign($payload);
$authHeaders = [ 'x-tenant-id' => $tenant, 'authorization' => 'Bearer ' . $token ];

// 1) Validar lote com item inválido (produto inexistente) — também garante criação das tabelas WMS Mobile
$batchId = 'BATCH-' . substr((string)mt_rand(1000, 999999), 0, 6);
$bodyValidate = [
  'items' => [
    [ 'product_id' => $productId, 'bin_code' => $binCode, 'quantity' => 3 ],
    [ 'product_code' => 'SKU-NAO-EXISTE', 'bin_id' => $binId, 'quantity' => 1 ]
  ]
];
$reqValidate = new Request($authHeaders, [], $bodyValidate, [], 'POST', '/api/wms/mobile/inventory/validate');
$resValidate = $kernel->handle($reqValidate);
assertTrue(in_array($resValidate->status, [200, 207]), 'POST /validate deve retornar 200 ou 207');
assertTrue(($resValidate->body['error_count'] ?? 0) >= 1, 'Validate deve apontar erro para produto inexistente');

// Registrar dispositivo mobile (API Key) após tabela existir
$apiKey = 'TEST-MOBILE-KEY';
// Reutilizar dispositivo se já existir
$check = $pdo->prepare('SELECT id FROM wms_mobile_devices WHERE api_key = ?');
$check->execute([$apiKey]);
$deviceId = (int)($check->fetch()['id'] ?? 0);
if ($deviceId <= 0) {
  $stmt = $pdo->prepare('INSERT INTO wms_mobile_devices (name, api_key, created_at) VALUES (?, ?, NOW())');
  $stmt->execute(['Coletor Teste', $apiKey]);
  $deviceId = (int)$pdo->lastInsertId();
}
assertTrue($deviceId > 0, 'Dispositivo mobile criado deve ter id > 0');

$apiHeaders = [ 'x-tenant-id' => $tenant, 'x-api-key' => $apiKey ];

// 2) Ingestão com API Key (itens mistos)
$bodyIngest = [
  'batch_id' => $batchId,
  'items' => [
    [ 'product_id' => $productId, 'bin_code' => $binCode, 'quantity' => 2.5 ],
    [ 'product_code' => 'SKU-NAO-EXISTE', 'bin_id' => $binId, 'quantity' => 1 ]
  ]
];
$reqIngest = new Request($apiHeaders, [], $bodyIngest, [], 'POST', '/api/wms/mobile/inventory/ingest');
$resIngest = $kernel->handle($reqIngest);
assertTrue(in_array($resIngest->status, [202, 207]), 'POST /ingest deve retornar 202 ou 207');
assertTrue(($resIngest->body['received_count'] ?? 0) === 2, 'Ingest deve receber 2 itens');

// 3) Criar sessão de inventário e confirmar lote
$reqStart = new Request($authHeaders, [], ['type' => 'geral', 'entries_count' => 2], [], 'POST', '/api/wms/inventory/start');
$resStart = $kernel->handle($reqStart);
assertTrue($resStart->status === 200, 'POST /inventory/start deve retornar 200');
$sessionId = (int)($resStart->body['created']['id'] ?? 0);
assertTrue($sessionId > 0, 'Sessão de inventário criada deve ter id > 0');

$reqConfirm = new Request($apiHeaders, [], ['batch_id' => $batchId, 'session_id' => $sessionId], [], 'POST', '/api/wms/mobile/inventory/confirm');
$resConfirm = $kernel->handle($reqConfirm);
assertTrue($resConfirm->status === 200, 'POST /confirm deve retornar 200');
assertTrue(($resConfirm->body['status'] ?? '') === 'confirmed', 'Status deve ser confirmed');

// 4) Processar fila e verificar persistência definitiva
$reqProcess = new Request($authHeaders, [], ['limit' => 10, 'session_id' => $sessionId], [], 'POST', '/api/wms/mobile/inventory/queue/process');
$resProcess = $kernel->handle($reqProcess);
assertTrue($resProcess->status === 200, 'POST /queue/process deve retornar 200');
assertTrue(($resProcess->body['processed'] ?? 0) >= 1, 'Processamento deve persistir pelo menos 1 item válido');

// Verificar gravação em wms_inventory_entries
$stmt = $pdo->prepare('SELECT COUNT(*) AS c FROM wms_inventory_entries WHERE session_id = ?');
$stmt->execute([$sessionId]);
$count = (int)($stmt->fetch()['c'] ?? 0);
assertTrue($count >= 1, 'wms_inventory_entries deve conter ao menos 1 registro');

echo "PASS: WmsMobileCollectorTest (ingest parcial, confirmação, processamento e persistência).\n";