<?php

declare(strict_types=1);

$root = getenv('POC_TARGET_ROOT');
$dialect = getenv('POC_DIALECT');
$baseUrl = rtrim((string)getenv('POC_BASE_URL'), '/');
if (!$root || !$baseUrl || !in_array($dialect, ['mysql', 'dm'], true)) exit(2);
foreach (['AI_HOST', 'AI_PORT', 'AI_SCHEMA', 'AI_USER', 'AI_PASSWORD'] as $part) {
    if (!getenv('POC_' . $part)) exit(2);
}
define('TP_ENV', 'poc');
define('BUSINESS', 'aizhct');
define('ENTERPRISE_NO', '10001');
require $root . '/vendor/autoload.php';
(new \think\App($root))->setEnvName('poc')->initialize();

$host = getenv('POC_AI_HOST');
$port = getenv('POC_AI_PORT');
$schema = getenv('POC_AI_SCHEMA');
$dsn = $dialect === 'dm'
    ? "dm:host=$host;port=$port;schema=$schema"
    : "mysql:host=$host;port=$port;dbname=$schema;charset=utf8mb4";
$pdo = new PDO($dsn, getenv('POC_AI_USER'), getenv('POC_AI_PASSWORD'),
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$userTable = $dialect === 'dm' ? 'YOSHOP_USER' : 'yoshop_user';
$activityTable = $dialect === 'dm' ? 'YOSHOP_ACTIVITY' : 'yoshop_activity';
$registerTable = $dialect === 'dm' ? 'YOSHOP_ACTIVITY_REGISTER' : 'yoshop_activity_register';
$activitySql = "SELECT ID FROM $activityTable WHERE STORE_ID=10001 AND STATUS=1 ORDER BY ID DESC "
    . ($dialect === 'dm' ? 'FETCH FIRST 1 ROW ONLY' : 'LIMIT 1');
$activityId = (int)$pdo->query($activitySql)->fetchColumn();
if ($activityId <= 0) throw new RuntimeException('Active activity fixture missing');
$marker = 'CDXACTREG' . strtoupper(bin2hex(random_bytes(5)));
$token = 'CDXACTREG-TOKEN-' . strtoupper(bin2hex(random_bytes(12)));
$userId = 0;
$expectFixedMissing = getenv('POC_EXPECT_FIXED_MISSING') === '1';
$request = static function (?string $auth, array $form) use ($baseUrl): array {
    $headers = "platform: POC\r\nContent-Type: application/x-www-form-urlencoded\r\n";
    if ($auth !== null) $headers .= 'Access-Token: ' . $auth . "\r\n";
    $options = [
        'method' => 'POST', 'header' => $headers,
        'content' => http_build_query(['form' => $form]),
        'timeout' => 15, 'ignore_errors' => true,
    ];
    $body = file_get_contents($baseUrl . '/api/activityRegister/add?storeId=10001', false,
        stream_context_create(['http' => $options]));
    $decoded = is_string($body) ? json_decode($body, true) : null;
    if (!is_array($decoded)) {
        throw new RuntimeException('Activity registration HTTP response not JSON: '
            . (string)($http_response_header[0] ?? 'unknown'));
    }
    unset($decoded['trace_id']);
    return $decoded;
};
$count = static function () use ($pdo, $registerTable, $activityId, &$userId): int {
    $read = $pdo->prepare('SELECT COUNT(*) FROM ' . $registerTable
        . ' WHERE ACTIVITY_ID=? AND USER_ID=? AND STORE_ID=10001');
    $read->execute([$activityId, $userId]);
    return (int)$read->fetchColumn();
};
try {
    $insert = $pdo->prepare('INSERT INTO ' . $userTable
        . ' (STORE_ID,MOBILE,NICK_NAME,BALANCE,GIFT_BALANCE,IS_DELETE,CREATE_TIME)'
        . ' VALUES (10001,?,?,?,?,0,?)');
    $insert->execute(['', $marker, '0.00', '0.00', time()]);
    $userId = (int)$pdo->lastInsertId();
    if ($userId <= 0 || $count() !== 0) {
        throw new RuntimeException('Activity registration precondition failed');
    }
    \think\facade\Cache::set($token, [
        'user' => ['user_id' => $userId], 'password_version' => 0,
        'login_type' => 'thirdparty',
    ], 300);
    $unauth = $request(null, ['activityId' => (string)$activityId]);
    if ((int)($unauth['status'] ?? 0) !== 401 || $count() !== 0) {
        throw new RuntimeException('Activity registration unauthenticated request mismatch');
    }
    $missing = $request($token, []);
    if ((int)($missing['status'] ?? 200) === 200 || $count() !== 0) {
        throw new RuntimeException('Activity registration missing argument accepted');
    }
    if ($expectFixedMissing
        && ((string)($missing['message'] ?? '') !== '活动ID不能为空'
            || array_keys($missing) !== ['status', 'message', 'data'])) {
        throw new RuntimeException('Activity registration missing form still leaks runtime error');
    }
    $invalid = $request($token, ['activityId' => 'not-an-integer']);
    if ((int)($invalid['status'] ?? 200) === 200 || $count() !== 0) {
        throw new RuntimeException('Activity registration invalid argument accepted');
    }
    $first = $request($token, ['activityId' => (string)$activityId]);
    if ((int)($first['status'] ?? 0) !== 200 || $count() !== 1) {
        throw new RuntimeException('Activity registration first request/readback mismatch');
    }
    $repeat = $request($token, ['activityId' => (string)$activityId]);
    if ((int)($repeat['status'] ?? 0) !== 200 || $count() !== 1
        || $repeat !== $first) {
        throw new RuntimeException('Activity registration idempotency/contract mismatch');
    }
    $read = $pdo->prepare('SELECT ACTIVITY_ID,USER_ID,STORE_ID FROM ' . $registerTable
        . ' WHERE ACTIVITY_ID=? AND USER_ID=?');
    $read->execute([$activityId, $userId]);
    $row = array_change_key_case((array)$read->fetch(PDO::FETCH_ASSOC));
    if ((int)($row['activity_id'] ?? 0) !== $activityId
        || (int)($row['user_id'] ?? 0) !== $userId
        || (int)($row['store_id'] ?? 0) !== 10001) {
        throw new RuntimeException('Activity registration database values mismatch');
    }
    echo json_encode(['dialect' => $dialect, 'status' => 'passed',
        'unauth' => $unauth, 'missing' => $missing, 'invalid' => $invalid,
        'registered' => $first, 'duplicate' => $repeat,
        'database_rows' => 1], JSON_UNESCAPED_UNICODE) . PHP_EOL;
} finally {
    \think\facade\Cache::delete($token);
    if ($userId > 0) {
        $pdo->prepare('DELETE FROM ' . $registerTable . ' WHERE ACTIVITY_ID=? AND USER_ID=?')
            ->execute([$activityId, $userId]);
        $pdo->prepare('DELETE FROM ' . $userTable . ' WHERE USER_ID=? AND NICK_NAME=?')
            ->execute([$userId, $marker]);
        $userCheck = $pdo->prepare('SELECT COUNT(*) FROM ' . $userTable . ' WHERE USER_ID=?');
        $userCheck->execute([$userId]);
        if ($count() !== 0 || (int)$userCheck->fetchColumn() !== 0) {
            throw new RuntimeException('Activity registration synthetic cleanup left rows');
        }
    }
}
