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

if (!defined('FASTPLAY_API_URL')) define('FASTPLAY_API_URL', 'https://api.painelcliente.com');
if (!defined('FASTPLAY_API_BOUQUET')) define('FASTPLAY_API_BOUQUET', '1,2,3,4');


function trial_req(string $key, $default = '') {
    static $jsonBody = null;
    if ($jsonBody === null) {
        $decoded = json_decode((string)file_get_contents('php://input'), true);
        $jsonBody = is_array($decoded) ? $decoded : [];
    }
    if (isset($_POST[$key])) return is_string($_POST[$key]) ? trim($_POST[$key]) : $_POST[$key];
    if (array_key_exists($key, $jsonBody)) return is_string($jsonBody[$key]) ? trim($jsonBody[$key]) : $jsonBody[$key];
    if (isset($_GET[$key])) return is_string($_GET[$key]) ? trim($_GET[$key]) : $_GET[$key];
    return $default;
}

function trial_sanitizar_whatsapp($whatsapp): string {
    return preg_replace('/[^0-9+]/', '', trim((string)$whatsapp));
}

function trial_curl_get_json(string $url, int $timeout = 12): ?array {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => $timeout,
        CURLOPT_CONNECTTIMEOUT => $timeout,
        CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_USERAGENT => 'TheFull-Teste/1.0',
    ]);
    $resp = curl_exec($ch);
    curl_close($ch);
    if (!$resp) return null;
    $json = json_decode($resp, true);
    return is_array($json) ? $json : null;
}

function trial_curl_post_json(string $url, array $payload, array $headers = [], int $timeout = 18, int $connectTimeout = 6): array {
    $allHeaders = array_merge(
        ['Content-Type: application/json', 'Accept: application/json', 'Connection: keep-alive'],
        array_values(array_filter(array_map('trim', $headers)))
    );
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
        CURLOPT_HTTPHEADER => $allHeaders,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_TIMEOUT => max(5, $timeout),
        CURLOPT_CONNECTTIMEOUT => max(3, min($connectTimeout, $timeout)),
        CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TCP_KEEPALIVE => 1,
        CURLOPT_USERAGENT => 'TheFull-Trial/2.0',
    ]);
    $startedAt = microtime(true);
    $response = curl_exec($ch);
    $error = curl_error($ch);
    $http = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $elapsedMs = (int)round((microtime(true) - $startedAt) * 1000);
    curl_close($ch);
    return ['response' => $response, 'error' => $error, 'http' => $http, 'elapsed_ms' => $elapsedMs];
}

function trial_has_invalid_sequence(string $value): bool {
    $digits = preg_replace('/\D+/', '', $value);
    $len = strlen($digits);
    if ($len < 4) return false;
    for ($i = 0; $i <= $len - 4; $i++) {
        $part = substr($digits, $i, 4);
        $a = (int)$part[0];
        $b = (int)$part[1];
        $c = (int)$part[2];
        $d = (int)$part[3];
        if ($b === $a + 1 && $c === $b + 1 && $d === $c + 1) return true;
        if ($b === $a - 1 && $c === $b - 1 && $d === $c - 1) return true;
    }
    return false;
}

function trial_random_login(string $prefix): string {
    $letters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
    $mix = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
    do {
        $value = $prefix;
        for ($i = 0; $i < 5; $i++) $value .= $letters[random_int(0, strlen($letters) - 1)];
        for ($i = 0; $i < 3; $i++) $value .= $mix[random_int(0, strlen($mix) - 1)];
        $lower = strtolower($value);
    } while (
        strpos($lower, 'test') !== false ||
        strpos($lower, 'teste') !== false ||
        trial_has_invalid_sequence($lower)
    );
    return $value;
}

function trial_random_credentials(): array {
    return [trial_random_login('cli'), trial_random_login('fp')];
}

function trial_create_sigma(string $apiUrl, string $apiToken, string $nome, string $whatsapp, string $macSalvar): array {
    $apiUrl = trim($apiUrl);
    if ($apiUrl === '') return ['ok' => false, 'message' => 'api_url_empty'];
    $payload = [
        'message' => 'teste',
        'action' => 'teste',
        'nome' => $nome,
        'name' => $nome,
        'whatsapp' => $whatsapp,
        'phone' => $whatsapp,
        'mac' => $macSalvar,
        'device_id' => $macSalvar,
    ];
    $headers = [];
    if (trim($apiToken) !== '') $headers[] = 'Authorization: Bearer ' . trim($apiToken);
    $ret = trial_curl_post_json($apiUrl, $payload, $headers, 18, 6);
    $body = trim((string)($ret['response'] ?? ''));
    $http = (int)($ret['http'] ?? 0);
    $curlError = trim((string)($ret['error'] ?? ''));
    if ($curlError !== '') return ['ok' => false, 'message' => 'sigma_connection_error'];
    $d = $body !== '' ? json_decode($body, true) : [];
    if (!is_array($d)) return ['ok' => false, 'message' => 'sigma_invalid_json'];
    if ($http < 200 || $http >= 300) {
        $msg = trim((string)trial_array_get_path($d, [['message'], ['mensagem'], ['error'], ['erro'], ['detail']], 'sigma_http_' . $http));
        return ['ok' => false, 'message' => $msg !== '' ? $msg : 'sigma_error'];
    }
    $status = strtolower(trim((string)trial_array_get_path($d, [['status'], ['result'], ['success'], ['ok']], 'success')));
    if (in_array($status, ['error', 'erro', 'failed', 'fail', 'false', 'invalid', '400'], true)) {
        $msg = trim((string)trial_array_get_path($d, [['message'], ['mensagem'], ['error'], ['erro'], ['detail']], 'sigma_error'));
        return ['ok' => false, 'message' => $msg !== '' ? $msg : 'sigma_error'];
    }
    $username = trim((string)trial_array_get_path($d, [
        ['username'], ['user'], ['login'], ['usuario'], ['dados', 'username'], ['dados', 'user'], ['dados', 'login'], ['data', 'username'], ['data', 'user'], ['data', 'login']
    ], ''));
    $password = trim((string)trial_array_get_path($d, [
        ['password'], ['senha'], ['pass'], ['dados', 'password'], ['dados', 'senha'], ['dados', 'pass'], ['data', 'password'], ['data', 'senha'], ['data', 'pass']
    ], ''));
    $exp = trial_parse_exp(trial_array_get_path($d, [
        ['exp_date'], ['expiration'], ['expire'], ['expires_at'], ['vencimento'], ['validade'], ['dados', 'exp_date'], ['dados', 'expiration'], ['dados', 'vencimento'], ['dados', 'validade'], ['data', 'exp_date'], ['data', 'expiration'], ['data', 'vencimento'], ['data', 'validade']
    ], 0));
    $dns = auth_normalize_dns((string)trial_array_get_path($d, [
        ['dns'], ['host'], ['server'], ['url'], ['dados', 'dns'], ['dados', 'host'], ['dados', 'url'], ['data', 'dns'], ['data', 'host'], ['data', 'url']
    ], ''));
    if ($username === '' || $password === '') return ['ok' => false, 'message' => 'api_missing_credentials'];
    return ['ok' => true, 'username' => $username, 'password' => $password, 'exp' => $exp, 'dns' => $dns, 'raw' => $d, 'elapsed_ms' => (int)($ret['elapsed_ms'] ?? 0)];
}

function trial_fastplay_endpoint(string $apiUrl, string $apiToken): string {
    $apiUrl = trim($apiUrl);
    $token = rawurlencode(trim($apiToken));
    if ($apiUrl === '') return '';
    if (strpos($apiUrl, '{token}') !== false) return str_replace('{token}', $token, $apiUrl);
    if (preg_match('~/trial_create/?$~i', $apiUrl)) return rtrim($apiUrl, '/') . '/' . $token;
    if (preg_match('~/trial_create/[^/?#]+$~i', $apiUrl)) return preg_replace('~/trial_create/[^/?#]+$~i', '/trial_create/' . $token, $apiUrl);
    return rtrim($apiUrl, '/') . '/trial_create/' . $token;
}

function trial_truthy($value): bool {
    if (is_bool($value)) return $value;
    if (is_numeric($value)) return (int)$value === 1;
    $v = strtolower(trim((string)$value));
    return in_array($v, ['1', 'true', 'ok', 'success', 'sucesso', 'created', 'criado'], true);
}

function trial_array_get_path(array $data, array $paths, $default = '') {
    foreach ($paths as $path) {
        $cur = $data;
        $ok = true;
        foreach ((array)$path as $key) {
            if (is_array($cur) && array_key_exists($key, $cur)) {
                $cur = $cur[$key];
            } else {
                $ok = false;
                break;
            }
        }
        if ($ok && $cur !== null && $cur !== '') return $cur;
    }
    return $default;
}

function trial_parse_exp($value): int {
    if (is_numeric($value)) return (int)$value;
    $raw = trim((string)$value);
    if ($raw === '') return 0;
    $ts = strtotime($raw);
    return $ts ? (int)$ts : 0;
}


function trial_control_file_path(): string {
    return __DIR__ . '/trial_generated.json';
}

function trial_control_read_all(): array {
    $file = trial_control_file_path();
    if (!is_file($file)) return [];
    $raw = @file_get_contents($file);
    $json = is_string($raw) && trim($raw) !== '' ? json_decode($raw, true) : [];
    return is_array($json) ? $json : [];
}

function trial_control_update(string $mac, callable $callback): array {
    $file = trial_control_file_path();
    $dir = dirname($file);
    if (!is_dir($dir)) @mkdir($dir, 0775, true);
    $fp = @fopen($file, 'c+');
    if (!$fp) return ['ok' => false, 'data' => []];
    try {
        @flock($fp, LOCK_EX);
        rewind($fp);
        $raw = stream_get_contents($fp);
        $data = is_string($raw) && trim($raw) !== '' ? json_decode($raw, true) : [];
        if (!is_array($data)) $data = [];
        $key = auth_normalize_mac($mac);
        $current = is_array($data[$key] ?? null) ? $data[$key] : [];
        $updated = $callback($current, $data);
        if (is_array($updated)) $data[$key] = $updated;
        rewind($fp);
        ftruncate($fp, 0);
        fwrite($fp, json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
        fflush($fp);
        @flock($fp, LOCK_UN);
        fclose($fp);
        return ['ok' => true, 'data' => $data[$key] ?? []];
    } catch (Throwable $e) {
        try { @flock($fp, LOCK_UN); fclose($fp); } catch (Throwable $e2) {}
        return ['ok' => false, 'data' => []];
    }
}

function trial_control_get(string $mac): array {
    $data = trial_control_read_all();
    $key = auth_normalize_mac($mac);
    return is_array($data[$key] ?? null) ? $data[$key] : [];
}

function trial_existing_success_payload(PDO $db, array $row, array $dnsList, string $provider = ''): array {
    $dnsSaved = auth_normalize_dns((string)($row['dns'] ?? ''));
    if ($dnsSaved !== '' && !in_array($dnsSaved, $dnsList, true)) array_unshift($dnsList, $dnsSaved);
    $exp = auth_parse_vencimento_to_timestamp($row['vencimento'] ?? 0);
    return [
        'status' => 'success',
        'already_generated' => true,
        'dados' => [
            'username' => trim((string)($row['username'] ?? '')),
            'senha' => trim((string)($row['password'] ?? '')),
            'password' => trim((string)($row['password'] ?? '')),
            'vencimento' => $exp > 0 ? date('Y-m-d H:i:s', $exp) : (string)($row['vencimento'] ?? ''),
            'nome_cliente' => trim((string)($row['nome_cliente'] ?? '')),
            'whatsapp' => trim((string)($row['whatsapp'] ?? '')),
            'provider' => $provider,
            'warning' => '',
        ],
        'dns' => array_values(array_unique(array_filter($dnsList))),
        'dns_salva' => $dnsSaved,
        'warning' => '',
    ];
}

function trial_is_db_locked(Throwable $e): bool {
    $msg = strtolower($e->getMessage());
    return strpos($msg, 'database is locked') !== false || strpos($msg, 'database table is locked') !== false || strpos($msg, 'database busy') !== false || strpos($msg, 'sqlstate[hy000]: general error: 5') !== false;
}

function trial_db_exec_retry(callable $callback, int $tries = 5, int $sleepMs = 120) {
    $last = null;
    for ($i = 0; $i < $tries; $i++) {
        try {
            return $callback();
        } catch (Throwable $e) {
            $last = $e;
            if (!trial_is_db_locked($e) || $i >= $tries - 1) {
                throw $e;
            }
            usleep($sleepMs * 1000);
            $sleepMs = min(1200, $sleepMs + 150);
        }
    }
    if ($last) throw $last;
    return false;
}

function trial_create_fastplay(string $apiUrl, string $apiToken, string $apiSecret, string $apiBouquet, string $nome, string $whatsapp, string $macSalvar = ''): array {
    $apiUrl = trim($apiUrl) !== '' ? trim($apiUrl) : FASTPLAY_API_URL;
    $apiToken = trim($apiToken);
    $apiSecret = trim($apiSecret);
    $apiBouquet = trim($apiBouquet) !== '' ? trim($apiBouquet) : FASTPLAY_API_BOUQUET;
    if ($apiToken === '' || $apiSecret === '') return ['ok' => false, 'message' => 'fastplay_token_or_secret_empty'];
    [$username, $password] = trial_random_credentials();
    $whatsappDigits = preg_replace('/\D+/', '', (string)$whatsapp);
    if ($whatsappDigits === '' || strlen($whatsappDigits) < 10) {
        $whatsappDigits = '5511999999999';
    }
    $bouquets = [];
    foreach (preg_split('/[,;\s]+/', $apiBouquet) as $b) {
        $b = trim((string)$b);
        if ($b !== '' && is_numeric($b)) $bouquets[] = (int)$b;
    }
    $bouquets = array_values(array_unique(array_filter($bouquets, fn($v) => (int)$v > 0)));
    if (empty($bouquets)) $bouquets = [1, 2, 3, 4];
    $endpoint = trial_fastplay_endpoint($apiUrl, $apiToken);
    if ($endpoint === '') return ['ok' => false, 'message' => 'api_url_empty'];
    $payload = [
        'secret' => $apiSecret,
        'username' => $username,
        'password' => $password,
        'idbouquet' => $bouquets,
        'email' => '',
        'whatsapp' => $whatsappDigits,
        'notes' => trim(($nome !== '' ? "Teste automático - {$nome}" : 'Teste automático') . ($macSalvar !== '' ? " - MAC {$macSalvar}" : '')),
    ];
    $ret = trial_curl_post_json($endpoint, $payload, [], 18, 6);
    $body = trim((string)($ret['response'] ?? ''));
    $http = (int)($ret['http'] ?? 0);
    $curlError = trim((string)($ret['error'] ?? ''));
    $d = $body !== '' ? json_decode($body, true) : [];
    if (!is_array($d)) {
        $lowerBody = strtolower($body);
        $d = (strpos($lowerBody, 'sucesso') !== false || strpos($lowerBody, 'success') !== false || strpos($lowerBody, 'criado') !== false) ? ['status' => 'success', 'message' => $body] : [];
    }
    if ($curlError !== '') return ['ok' => false, 'message' => 'fastplay_connection_error'];
    if ($http < 200 || $http >= 300) {
        $msg = trim((string)trial_array_get_path($d, [['mens'], ['message'], ['mensagem'], ['error'], ['erro'], ['errors', 0], ['detail']], 'fastplay_http_' . $http));
        return ['ok' => false, 'message' => $msg !== '' ? $msg : 'fastplay_error'];
    }
    $statusCode = (int)($d['statusCode'] ?? $http);
    if ($statusCode !== 200) {
        $msg = trim((string)trial_array_get_path($d, [['mens'], ['message'], ['mensagem'], ['error'], ['erro'], ['detail']], 'fastplay_status_' . $statusCode));
        return ['ok' => false, 'message' => $msg !== '' ? $msg : 'fastplay_error'];
    }
    if (!array_key_exists('result', $d) || !trial_truthy($d['result'])) {
        $msg = trim((string)trial_array_get_path($d, [['mens'], ['message'], ['mensagem'], ['error'], ['erro'], ['detail']], 'fastplay_result_false'));
        return ['ok' => false, 'message' => $msg !== '' ? $msg : 'fastplay_error'];
    }

    $hasExplicitFailure = false;
    foreach (['success', 'ok', 'status'] as $key) {
        if (!array_key_exists($key, $d)) continue;
        $value = $d[$key];
        if ($key === 'status') {
            $status = strtolower(trim((string)$value));
            if (in_array($status, ['error', 'erro', 'failed', 'fail', 'false', 'invalid', '400'], true)) $hasExplicitFailure = true;
        } elseif (!trial_truthy($value)) {
            $hasExplicitFailure = true;
        }
    }
    if ($hasExplicitFailure) {
        $msg = trim((string)trial_array_get_path($d, [['mens'], ['message'], ['mensagem'], ['error'], ['erro'], ['errors', 0], ['detail']], 'fastplay_error'));
        return ['ok' => false, 'message' => $msg !== '' ? $msg : 'fastplay_error'];
    }
    $userRet = trim((string)trial_array_get_path($d, [
        ['username'], ['user'], ['login'], ['data', 'username'], ['data', 'user'], ['data', 'login'], ['dados', 'username'], ['dados', 'user'], ['dados', 'login']
    ], $username));
    $passRet = trim((string)trial_array_get_path($d, [
        ['password'], ['senha'], ['pass'], ['data', 'password'], ['data', 'senha'], ['data', 'pass'], ['dados', 'password'], ['dados', 'senha'], ['dados', 'pass']
    ], $password));
    $exp = trial_parse_exp(trial_array_get_path($d, [
        ['exp_date'], ['expiration'], ['expire'], ['expires_at'], ['data', 'exp_date'], ['data', 'expiration'], ['data', 'expire'], ['data', 'expires_at'], ['dados', 'exp_date'], ['dados', 'expiration'], ['dados', 'expire'], ['dados', 'expires_at']
    ], 0));
    $dns = auth_normalize_dns((string)trial_array_get_path($d, [
        ['dns'], ['host'], ['server'], ['url'], ['data', 'dns'], ['data', 'host'], ['data', 'url'], ['dados', 'dns'], ['dados', 'host'], ['dados', 'url']
    ], ''));
    if ($userRet === '' || $passRet === '') return ['ok' => false, 'message' => 'api_missing_credentials'];
    if ($exp <= 0) $exp = time() + (4 * 3600);
    return ['ok' => true, 'username' => $userRet, 'password' => $passRet, 'exp' => $exp, 'dns' => $dns, 'raw' => $d, 'payload' => ['username' => $username, 'idbouquet' => $bouquets], 'elapsed_ms' => (int)($ret['elapsed_ms'] ?? 0)];
}

function trial_user_already_generated_test(array $userRow): bool {
    $teste = strtolower(trim((string)($userRow['teste'] ?? '0')));
    if (in_array($teste, ['1', 'true', 'sim', 'yes', 'ativo', 'teste'], true)) return true;
    foreach (['teste_criado_at', 'whatsapp_trial_started_at', 'whatsapp_account_created_at'] as $col) {
        $val = trim((string)($userRow[$col] ?? ''));
        if ($val !== '' && $val !== '0') return true;
    }
    return false;
}

function trial_validate_dns_credentials_with_retry(array $dnsList, string $username, string $password, int $attempts = 1): array {
    $attempts = max(1, min(8, $attempts));
    $last = ['ok' => false, 'expired' => false, 'dns' => '', 'exp' => 0, 'message' => 'invalid'];
    for ($i = 0; $i < $attempts; $i++) {
        $last = auth_validate_dns_credentials($dnsList, $username, $password);
        if (!empty($last['ok']) || !empty($last['expired'])) return $last;
        if ($i < $attempts - 1) usleep(700000);
    }
    return $last;
}

function trial_save_user(PDO $db, string $macSalvar, string $dnsEscolhida, string $username, string $password, int $exp, string $nome, string $whatsapp, string $provider = 'sigma', string $deviceType = 'tv'): bool {
    $agora = time();
    $macSalvar = auth_normalize_mac($macSalvar);
    if ($macSalvar === '') return false;
    $deviceType = da_normalize_device_type($deviceType);

    return (bool)trial_db_exec_retry(function() use ($db, $macSalvar, $dnsEscolhida, $username, $password, $exp, $nome, $whatsapp, $deviceType, $agora) {
        $st = $db->prepare('SELECT * FROM usuarios WHERE mac = ? LIMIT 1');
        $st->execute([$macSalvar]);
        $existing = $st->fetch(PDO::FETCH_ASSOC) ?: null;
        $st->closeCursor();

        if ($existing) {
            $up = $db->prepare("UPDATE usuarios SET dns = ?, username = ?, password = ?, vencimento = ?, status = 'ativo', nome_cliente = ?, whatsapp = ?, teste = 1, teste_criado_at = ?, whatsapp_trial_started_at = ?, whatsapp_account_created_at = ?, login_mode = 'mac', device_type = ?, last_device_type = ? WHERE mac = ?");
            $ok = $up->execute([$dnsEscolhida, $username, $password, (string)$exp, $nome, $whatsapp, $agora, $agora, $agora, $deviceType, $deviceType, $macSalvar]);
            $up->closeCursor();
            return $ok;
        }

        $activationCode = auth_generate_activation_code($db);
        $ins = $db->prepare("INSERT INTO usuarios (mac, dns, username, password, vencimento, status, nome_cliente, whatsapp, teste, teste_criado_at, whatsapp_trial_started_at, whatsapp_account_created_at, login_mode, device_type, last_device_type, activation_code, usuario_id)
            VALUES (?, ?, ?, ?, ?, 'ativo', ?, ?, 1, ?, ?, ?, 'mac', ?, ?, ?, 0)");
        $ok = $ins->execute([$macSalvar, $dnsEscolhida, $username, $password, (string)$exp, $nome, $whatsapp, $agora, $agora, $agora, $deviceType, $deviceType, $activationCode]);
        $ins->closeCursor();
        return $ok;
    }, 5, 120);
}

function gerar_teste_service(PDO $db, ?string $mac, array $cfg, array $options = []): array {
    if (!$mac) return ['status' => 'error', 'message' => 'mac_required'];
    $nome = trim((string)($options['nome'] ?? trial_req('nome', '')));
    $whatsapp = trial_sanitizar_whatsapp((string)($options['whatsapp'] ?? trial_req('whatsapp', '')));
    $deviceType = da_normalize_device_type((string)($options['device_type'] ?? trial_req('device_type', 'tv')));
    $macSalvar = auth_normalize_mac($mac);
    if ($nome === '') $nome = 'Cliente MAC ' . strtoupper(substr(str_replace(':', '', $macSalvar), -4));
    if ($whatsapp === '' || strlen(preg_replace('/\D+/', '', $whatsapp)) < 10) $whatsapp = '5511999999999';
    if ($macSalvar === '' || strlen(str_replace(':', '', $macSalvar)) !== 12) return ['status' => 'error', 'message' => 'mac_invalid'];

    $check = $db->prepare('SELECT * FROM usuarios WHERE mac = ? LIMIT 1');
    $check->execute([$macSalvar]);
    $existing = $check->fetch(PDO::FETCH_ASSOC) ?: null;
    $dnsList = auth_get_dns_list($db);
    if (empty($dnsList)) return ['status' => 'error', 'message' => 'dns_empty'];

    $control = trial_control_get($macSalvar);
    if ($existing && auth_user_has_credentials($existing) && (trial_user_already_generated_test($existing) || !empty($control['generated']))) {
        return trial_existing_success_payload($db, $existing, $dnsList, strtolower(trim((string)($cfg['provider'] ?? ''))));
    }
    if (!$existing && !empty($control['generated'])) {
        return ['status' => 'blocked', 'message' => 'Este aparelho já gerou teste grátis.'];
    }
    if ($existing && trial_user_already_generated_test($existing) && !auth_user_has_credentials($existing)) {
        return ['status' => 'blocked', 'message' => 'Este aparelho já gerou teste grátis. Aguarde liberação no painel.'];
    }

    $provider = strtolower(trim((string)($cfg['provider'] ?? 'sigma')));
    if (!in_array($provider, ['sigma', 'fastplay'], true)) $provider = 'sigma';

    if ($provider === 'fastplay') {
        $apiUrl = FASTPLAY_API_URL;
        $apiToken = trim((string)($cfg['fastplay_token'] ?? $cfg['api_token'] ?? ''));
        $apiSecret = trim((string)($cfg['fastplay_secret'] ?? $cfg['api_secret'] ?? ''));
        $apiBouquet = FASTPLAY_API_BOUQUET;
        if ($apiToken === '') return ['status' => 'error', 'message' => 'fastplay_token_empty'];
        if ($apiSecret === '') return ['status' => 'error', 'message' => 'fastplay_secret_empty'];
    } else {
        $apiUrl = trim((string)($cfg['sigma_api_url'] ?? $cfg['api_url'] ?? ''));
        $apiToken = trim((string)($cfg['sigma_token'] ?? $cfg['api_token'] ?? ''));
        $apiSecret = '';
        $apiBouquet = '';
        if ($apiUrl === '') return ['status' => 'error', 'message' => 'sigma_api_url_empty'];
    }

    $lock = trial_control_update($macSalvar, function(array $current) use ($provider) {
        $now = time();
        $started = (int)($current['started_at'] ?? 0);
        if (($current['status'] ?? '') === 'creating' && $started > 0 && ($now - $started) < 35) {
            $current['duplicate_creating'] = 1;
            $current['updated_at'] = $now;
            return $current;
        }
        $current['status'] = 'creating';
        $current['provider'] = $provider;
        $current['started_at'] = $now;
        $current['updated_at'] = $now;
        $current['duplicate_creating'] = 0;
        return $current;
    });
    $lockData = is_array($lock['data'] ?? null) ? $lock['data'] : [];
    if (!empty($lockData['duplicate_creating'])) {
        return ['status' => 'creating', 'message' => 'Teste em criação. Aguarde alguns segundos e tente novamente.'];
    }

    if (!$existing) {
        try {
            auth_ensure_pending_mac($db, $macSalvar, $deviceType);
        } catch (Throwable $e) {
            if (!trial_is_db_locked($e)) {
                throw $e;
            }
        }
    }

    $retApi = $provider === 'fastplay'
        ? trial_create_fastplay($apiUrl, $apiToken, $apiSecret, $apiBouquet, $nome, $whatsapp, $macSalvar)
        : trial_create_sigma($apiUrl, $apiToken, $nome, $whatsapp, $macSalvar);
    if (empty($retApi['ok'])) {
        trial_control_update($macSalvar, function(array $current) use ($retApi) {
            $current['status'] = 'error';
            $current['error'] = (string)($retApi['message'] ?? 'trial_error');
            $current['updated_at'] = time();
            return $current;
        });
        return [
            'status' => 'error',
            'message' => (string)($retApi['message'] ?? 'trial_error'),
            'api_raw' => $retApi['raw'] ?? null,
            'api_payload' => $retApi['payload'] ?? null
        ];
    }

    $username = trim((string)$retApi['username']);
    $password = trim((string)$retApi['password']);
    $exp = (int)($retApi['exp'] ?? 0);

    // Resposta rápida: o endpoint de teste apenas cria e salva as credenciais.
    // A validação Xtream completa será executada pelo mesmo fluxo do botão Entrar
    // no aplicativo. Isso evita várias chamadas sequenciais ao player_api antes de
    // devolver usuário e senha para a LoginActivity.
    $dnsApi = auth_normalize_dns((string)($retApi['dns'] ?? ''));
    $dnsExistente = auth_normalize_dns((string)($existing['dns'] ?? ''));
    $dnsEscolhida = $dnsApi !== '' ? $dnsApi : ($dnsExistente !== '' ? $dnsExistente : auth_normalize_dns((string)($dnsList[0] ?? '')));
    if ($dnsEscolhida === '') return ['status' => 'invalid', 'message' => 'dns_invalid'];
    if ($dnsEscolhida !== '' && !in_array($dnsEscolhida, $dnsList, true)) array_unshift($dnsList, $dnsEscolhida);
    if ($exp <= 0) $exp = time() + 86400;
    $validationWarning = '';

    try {
        $saved = trial_save_user($db, $macSalvar, $dnsEscolhida, $username, $password, $exp, $nome, $whatsapp, $provider, $deviceType);
    } catch (Throwable $e) {
        $msg = trial_is_db_locked($e) ? 'database_busy_try_again' : 'db_insert_error';
        trial_control_update($macSalvar, function(array $current) use ($msg) {
            $current['status'] = 'error';
            $current['error'] = $msg;
            $current['updated_at'] = time();
            return $current;
        });
        return ['status' => 'error', 'message' => $msg];
    }

    if (!$saved) {
        trial_control_update($macSalvar, function(array $current) {
            $current['status'] = 'error';
            $current['error'] = 'db_insert_error';
            $current['updated_at'] = time();
            return $current;
        });
        return ['status' => 'error', 'message' => 'db_insert_error'];
    }

    trial_control_update($macSalvar, function(array $current) use ($username, $password, $dnsEscolhida, $exp, $provider) {
        $current['status'] = 'success';
        $current['generated'] = true;
        $current['username'] = $username;
        $current['password'] = $password;
        $current['dns'] = $dnsEscolhida;
        $current['exp'] = $exp;
        $current['provider'] = $provider;
        $current['updated_at'] = time();
        return $current;
    });

    return [
        'status' => 'success',
        'dados' => [
            'username' => $username,
            'senha' => $password,
            'vencimento' => date('Y-m-d H:i:s', $exp),
            'nome_cliente' => $nome,
            'whatsapp' => $whatsapp,
            'provider' => $provider,
            'warning' => $validationWarning,
            'login_required' => true,
        ],
        'provider' => $provider,
        'login_required' => true,
        'generation_ms' => (int)($retApi['elapsed_ms'] ?? 0),
        'dns' => array_values(array_unique(array_filter($dnsList))),
        'dns_salva' => $dnsEscolhida,
        'warning' => $validationWarning,
    ];
}
