<?php
/**
 * 一键执行渠道与游戏配置初始化（需已备份数据库）
 * 用法：在 server 目录执行 php db/run_all_init.php
 */
declare(strict_types=1);

define('BASE_PATH', dirname(__DIR__));

require_once BASE_PATH . '/vendor/autoload.php';

if (class_exists(\Dotenv\Dotenv::class) && is_file(BASE_PATH . '/.env')) {
    if (method_exists(\Dotenv\Dotenv::class, 'createUnsafeMutable')) {
        \Dotenv\Dotenv::createUnsafeMutable(BASE_PATH)->load();
    } else {
        \Dotenv\Dotenv::createMutable(BASE_PATH)->load();
    }
}

// 加载配置（排除 route.php，避免 CLI 报错）
\Webman\Config::load(BASE_PATH . '/config', ['route', 'plugin']);
\Webman\ThinkOrm\ThinkOrm::start(null);

use app\dice\service\DiceChannelConfigService;
use plugin\saiadmin\app\model\system\SystemDept;
use plugin\saiadmin\app\model\system\SystemUser;
use support\think\Db;

function cliPdo(): PDO
{
    $host = getenv('DB_HOST') ?: '127.0.0.1';
    $port = getenv('DB_PORT') ?: '3306';
    $db = getenv('DB_NAME') ?: '';
    $user = getenv('DB_USER') ?: '';
    $pass = getenv('DB_PASSWORD') ?: '';
    $dsn = "mysql:host={$host};port={$port};dbname={$db};charset=utf8mb4";
    return new PDO($dsn, $user, $pass, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ]);
}

function runSqlFile(PDO $pdo, string $path, string $label, bool $alterOnly = false): void
{
    echo "\n=== {$label} ===\n";
    if (!is_file($path)) {
        echo "跳过：文件不存在\n";
        return;
    }
    $sql = file_get_contents($path);
    $sql = preg_replace('/--.*$/m', '', $sql);
    $parts = array_filter(array_map('trim', explode(';', $sql)));
    $ok = 0;
    $skip = 0;
    foreach ($parts as $statement) {
        if ($statement === '') {
            continue;
        }
        if ($alterOnly && stripos($statement, 'ALTER TABLE') !== 0) {
            continue;
        }
        try {
            $pdo->exec($statement);
            $ok++;
        } catch (PDOException $e) {
            $msg = $e->getMessage();
            $isAlter = stripos($statement, 'ALTER TABLE') === 0;
            if ($isAlter && (stripos($msg, 'Duplicate column') !== false
                || stripos($msg, 'Duplicate key name') !== false)) {
                $skip++;
            } elseif (!$isAlter) {
                echo "  [警告] " . substr($msg, 0, 120) . "\n";
                $skip++;
            } else {
                echo "  [错误] {$msg}\n";
                throw $e;
            }
        }
    }
    echo "完成：成功 {$ok} 条" . ($skip > 0 ? "，跳过 {$skip} 条（字段已存在）" : '') . "\n";
}

function getRootDeptId(int $deptId): ?int
{
    $currentId = $deptId;
    $visited = [];
    while ($currentId > 0 && !isset($visited[$currentId])) {
        $visited[$currentId] = true;
        $dept = SystemDept::find($currentId);
        if (!$dept) {
            return null;
        }
        $parentId = (int) ($dept->parent_id ?? 0);
        if ($parentId === 0) {
            return $currentId;
        }
        $currentId = $parentId;
    }
    return $currentId > 0 ? $currentId : null;
}

echo "========== 大富翁渠道/配置初始化 ==========\n";
echo '数据库: ' . (getenv('DB_NAME') ?: '') . '@' . (getenv('DB_HOST') ?: '') . "\n";

$pdo = cliPdo();

runSqlFile($pdo, __DIR__ . '/dice_tables_add_dept_id.sql', '1. dice 表增加 dept_id', true);
runSqlFile($pdo, __DIR__ . '/dept_flatten_channels.sql', '2. 渠道扁平化 SQL');

echo "\n=== 3. 渠道扁平化 PHP（多级用户归并 + 删除子渠道） ===\n";
Db::transaction(function () {
    $users = SystemUser::where('dept_id', '>', 0)->select();
    $moved = 0;
    foreach ($users as $user) {
        $deptId = (int) $user->dept_id;
        $rootId = getRootDeptId($deptId);
        if ($rootId !== null && $rootId !== $deptId) {
            SystemUser::where('id', $user->id)->update(['dept_id' => $rootId]);
            echo "  用户 {$user->id}: dept {$deptId} -> {$rootId}\n";
            $moved++;
        }
    }
    $childIds = SystemDept::where('parent_id', '>', 0)->column('id');
    if (!empty($childIds)) {
        SystemDept::destroy($childIds);
        echo '  已删除子渠道: ' . implode(',', $childIds) . "\n";
    } else {
        echo "  无子渠道需删除\n";
    }
    SystemDept::where('id', '>', 0)->update(['parent_id' => 0, 'level' => '0']);
    echo "  用户归并 {$moved} 人，渠道扁平化完成\n";
});

$service = new DiceChannelConfigService();

echo "\n=== 3.5 配置表复合键与默认模板 dept_id=0 ===\n";
$service->ensureConfigCompositeKeys();
echo "  dice_config / dice_reward_config: ok\n";

echo "\n=== 3.6 彩金池配置按渠道唯一（dept_id + name） ===\n";
try {
    $indexes = Db::query("SHOW INDEX FROM `dice_lottery_pool_config` WHERE Key_name = 'dice_lottery_poll_config_unique'");
    if (!empty($indexes)) {
        Db::execute('ALTER TABLE `dice_lottery_pool_config` DROP INDEX `dice_lottery_poll_config_unique`');
        echo "  已移除 name 全局唯一索引\n";
    }
    $uk = Db::query("SHOW INDEX FROM `dice_lottery_pool_config` WHERE Key_name = 'uk_dept_name'");
    if (empty($uk)) {
        Db::execute('ALTER TABLE `dice_lottery_pool_config` ADD UNIQUE KEY `uk_dept_name` (`dept_id`, `name`)');
        echo "  已添加 uk_dept_name(dept_id, name)\n";
    } else {
        echo "  uk_dept_name 已存在\n";
    }
} catch (\Throwable $e) {
    echo "  跳过: {$e->getMessage()}\n";
}

echo "\n=== 4. 将现有配置设为默认模板（dept_id=0） ===\n";
$tables = [
    'dice_config',
    'dice_ante_config',
    'dice_lottery_pool_config',
    'dice_reward_config',
    'dice_reward',
    'dice_game',
];
foreach ($tables as $table) {
    try {
        Db::table($table)->update(['dept_id' => 0]);
        echo "  {$table}: ok\n";
    } catch (\Throwable $e) {
        echo "  {$table}: 跳过 ({$e->getMessage()})\n";
    }
}

echo "\n=== 5. 为所有渠道从默认模板复制配置 ===\n";
$summary = $service->syncAllChannelsFromDefault();
foreach ($summary as $deptId => $info) {
    $copied = implode(',', $info['copied'] ?? []) ?: '无';
    $skipped = implode(',', $info['skipped'] ?? []) ?: '无';
    echo "  渠道 {$deptId}: 复制 [{$copied}]，跳过 [{$skipped}]\n";
}

echo "\n=== 6. 修复无效渠道并回填 dept_id ===\n";
echo "  无效渠道归并: ";
print_r($service->repairOrphanDeptReferences());
echo "  回填: ";
print_r($service->backfillDataDeptId());

$deptCount = SystemDept::count();
echo "\n当前顶级渠道数: {$deptCount}\n";
echo "========== 全部初始化完成 ==========\n";
