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

use Gestoreasy\Core\Kernel;
use Gestoreasy\Core\Http\Request;
use Gestoreasy\Core\Auth\Jwt;
use Gestoreasy\Core\Admin\ConnectionManager as AdminDb;
use Gestoreasy\Core\Tenant\ConnectionManager as TenantDb;
use Gestoreasy\Core\Tenant\TenantAdmin;

function assertStatus($resp, $expected, $msg) { $ok = ($resp->status ?? null) === $expected; echo ($ok ? "OK" : "FAIL") . ": $msg (got=" . ($resp->status ?? '?') . ", expected=$expected)\n"; if (!$ok) { exit(1); } }
function assertJsonHas($json, $path, $msg) { $parts = explode('.', $path); $cur = $json; foreach ($parts as $p) { if (!is_array($cur) || !array_key_exists($p, $cur)) { echo "FAIL: $msg (missing $path)\n"; exit(1); } $cur = $cur[$p]; } echo "OK: $msg\n"; }

$kernel = new Kernel();

// Preparar admin DB: garantir tenant default, planos basic e premium compatíveis
$admin = AdminDb::db();
// Garantir tenant default existe
$rowT = $admin->prepare("SELECT id FROM tenants WHERE tenant_id = ? LIMIT 1");
$rowT->execute(['default']);
$tenantRow = $rowT->fetch();
if (!$tenantRow) {
    $admin->prepare('INSERT INTO tenants (tenant_id, access_enabled) VALUES (?, ?)')->execute(['default', 1]);
} else {
    $admin->prepare('UPDATE tenants SET access_enabled = 1 WHERE tenant_id = ?')->execute(['default']);
}
// Criar/obter planos
$admin->prepare('INSERT IGNORE INTO plans (name, price_brl, cycle, active, modules_json) VALUES (?,?,?,?,?)')
    ->execute(['basic', 0.00, 'mensal', 1, json_encode(['clientes','produtos','vendas','compras'])]);
$admin->prepare('INSERT IGNORE INTO plans (name, price_brl, cycle, active, modules_json) VALUES (?,?,?,?,?)')
    ->execute(['premium', 99.90, 'mensal', 1, json_encode(['clientes','produtos','vendas','compras','integrations.googlecalendar'])]);
$planBasicId = (int)($admin->query("SELECT id FROM plans WHERE name = 'basic' LIMIT 1")->fetch()['id'] ?? 0);
$planPremiumId = (int)($admin->query("SELECT id FROM plans WHERE name = 'premium' LIMIT 1")->fetch()['id'] ?? 0);

// Rodar /health com tenant default para aplicar migrações do tenant
$headersHealth = ['x-tenant-id' => 'default'];
$reqHealth = new Request($headersHealth, [], [], [], 'GET', '/health');
$kernel->handle($reqHealth);

// Garantir que as permissões do Google Calendar existam para o teste
$pdoTenant = TenantDb::forTenant('default');
$driverName = $pdoTenant->getAttribute(\PDO::ATTR_DRIVER_NAME);

$permCheck = $pdoTenant->query("SELECT name FROM permissions WHERE name LIKE 'integrations.googlecalendar%'")->fetchAll();

// Se as permissões não existem, criar para o teste
if (empty($permCheck)) {
    if ($driverName === 'sqlite') {
        $pdoTenant->exec("INSERT OR IGNORE INTO permissions (name) VALUES ('integrations.googlecalendar.read')");
        $pdoTenant->exec("INSERT OR IGNORE INTO permissions (name) VALUES ('integrations.googlecalendar.manage')");
    } else {
        $pdoTenant->exec("INSERT IGNORE INTO permissions (name) VALUES ('integrations.googlecalendar.read')");
        $pdoTenant->exec("INSERT IGNORE INTO permissions (name) VALUES ('integrations.googlecalendar.manage')");
    }
}

// Tokens
$adminToken = Jwt::sign(['sub' => 1, 'email' => 'admin@local', 'name' => 'Admin', 'tenant' => 'default', 'roles' => ['admin'], 'impersonated' => true]);

// Usuário básico (não-admin)
$pdoTenant = TenantDb::forTenant('default');
$pwd = password_hash('basic123', PASSWORD_BCRYPT);
$stmtUser = $pdoTenant->prepare("SELECT id FROM users WHERE email = ? LIMIT 1");
$stmtUser->execute(['user@basic']);
$userRow = $stmtUser->fetch();
if (!$userRow) {
    $pdoTenant->prepare("INSERT INTO users (email, password_hash, name) VALUES (?,?,?)")
        ->execute(['user@basic', $pwd, 'Usuário Básico']);
    $stmtUser->execute(['user@basic']);
    $userRow = $stmtUser->fetch();
}
$userId = (int)($userRow['id'] ?? 0);
$userToken = Jwt::sign(['sub' => $userId, 'email' => 'user@basic', 'name' => 'Usuário Básico', 'tenant' => 'default', 'roles' => []]);

// Cenário 1: Plano basic (sem googlecalendar) -> usuário básico deve receber 403 module_disabled
$admin->prepare('UPDATE tenants SET plan_id = ? WHERE tenant_id = ?')->execute([$planBasicId, 'default']);
$headers1 = ['x-tenant-id' => 'default', 'authorization' => 'Bearer ' . $userToken];
$req1 = new Request($headers1, [], [], [], 'GET', '/api/integrations/google-calendar/config');
$resp1 = $kernel->handle($req1);
assertStatus($resp1, 403, 'Usuário básico com plano basic deve ser bloqueado');
assertJsonHas(is_array($resp1->body) ? $resp1->body : [], 'error.code', 'Resposta de bloqueio deve conter código');

// Cenário 2: Plano basic, mas admin@local deve acessar (bypass)
$headers2 = ['x-tenant-id' => 'default', 'authorization' => 'Bearer ' . $adminToken];
$req2 = new Request($headers2, [], [], [], 'GET', '/api/integrations/google-calendar/config');
$resp2 = $kernel->handle($req2);
assertStatus($resp2, 200, 'Admin deve acessar mesmo no plano basic');

// Cenário 3: Plano premium (com googlecalendar) -> usuário básico precisa permissão de leitura
// Vincular permissão read ao usuário via role 'integrator'
// Role 'integrator'
$stmtRole = $pdoTenant->query("SELECT id FROM roles WHERE name = 'integrator' LIMIT 1");
$roleRow = $stmtRole->fetch();
if (!$roleRow) { $pdoTenant->prepare("INSERT INTO roles (name) VALUES ('integrator')")->execute(); $roleRow = $pdoTenant->query("SELECT id FROM roles WHERE name = 'integrator' LIMIT 1")->fetch(); }
$roleId = (int)($roleRow['id'] ?? 0);

// Permissão googlecalendar.read
$permReadRow = $pdoTenant->query("SELECT id FROM permissions WHERE name = 'integrations.googlecalendar.read' LIMIT 1")->fetch();
if (!$permReadRow) {
    echo "FAIL: Permissão 'integrations.googlecalendar.read' não encontrada. Migrações podem não ter sido aplicadas.\n";
    exit(1);
}
$permReadId = (int)$permReadRow['id'];
// Vincular permissão à role se não existir
$stmtRp = $pdoTenant->prepare('SELECT 1 FROM role_permissions WHERE role_id = ? AND permission_id = ? LIMIT 1');
$stmtRp->execute([$roleId, $permReadId]);
if (!$stmtRp->fetch()) { $pdoTenant->prepare('INSERT INTO role_permissions (role_id, permission_id) VALUES (?, ?)')->execute([$roleId, $permReadId]); }
// Vincular role ao usuário se não existir
$stmtUr = $pdoTenant->prepare('SELECT 1 FROM user_roles WHERE user_id = ? AND role_id = ? LIMIT 1');
$stmtUr->execute([$userId, $roleId]);
if (!$stmtUr->fetch()) { $pdoTenant->prepare('INSERT INTO user_roles (user_id, role_id) VALUES (?, ?)')->execute([$userId, $roleId]); }

$admin->prepare('UPDATE tenants SET plan_id = ? WHERE tenant_id = ?')->execute([$planPremiumId, 'default']);
$headers3 = ['x-tenant-id' => 'default', 'authorization' => 'Bearer ' . $userToken];
$req3 = new Request($headers3, [], [], [], 'GET', '/api/integrations/google-calendar/config');
$resp3 = $kernel->handle($req3);
assertStatus($resp3, 200, 'Usuário com plano premium e permissão deve acessar');
assertJsonHas(is_array($resp3->body) ? $resp3->body : [], 'config', 'Resposta deve conter config');

echo "All GoogleCalendar access tests passed.\n";