import HelpOutlineOutlined from "@mui/icons-material/HelpOutlineOutlined";
import AccountBalanceWalletOutlined from "@mui/icons-material/AccountBalanceWalletOutlined";
import AddCircleOutlineOutlined from "@mui/icons-material/AddCircleOutlineOutlined";
import RefreshOutlined from "@mui/icons-material/RefreshOutlined";
import SettingsOutlined from "@mui/icons-material/SettingsOutlined";
import TuneOutlined from "@mui/icons-material/TuneOutlined";
import MenuItem from "@mui/material/MenuItem";
import TextField from "@mui/material/TextField";
import Tooltip from "@mui/material/Tooltip";
import { useCallback, useEffect, useMemo, useState } from "react";
import { PERMISSIONS } from "@/app/permissions";
import { useAuth } from "@/app/auth/AuthProvider.jsx";
import {
    adjustSelfGameStakePool,
    getSelfGameNewUserPolicy,
    listSelfGameStakePools,
    listSelfGames,
    updateDiceConfig,
    updateSelfGameNewUserPolicy,
    updateSelfGameStakePool,
} from "@/features/games/api";
import styles from "@/features/games/games.module.css";
import {
    AdminActionIconButton,
    AdminListBody,
    AdminListPage,
    AdminListToolbar,
    AdminRowActions,
} from "@/shared/ui/AdminListLayout.jsx";
import {
    AdminFormDialog,
    AdminFormFieldGrid,
    AdminFormSection,
    AdminFormSwitchField,
} from "@/shared/ui/AdminFormDialog.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import { PageSkeleton } from "@/shared/ui/PageSkeleton.jsx";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import { formatMillis } from "@/shared/utils/time.js";

const defaultConfigForm = {
    status: "active",
    stakeOptionsText: "100,500,1000,8000",
    feeBps: 500,
    poolBps: 100,
    minPlayers: 2,
    maxPlayers: 2,
    robotEnabled: true,
    robotMatchWaitMs: 3000,
};

const defaultStakePoolConfigForm = {
    stakeCoin: "",
    targetBalanceCoin: "",
    safeBalanceCoin: "",
    warningBalanceCoin: "",
    dangerBalanceCoin: "",
    status: "active",
};

const defaultStakePoolAdjustForm = {
    stakeCoin: "",
    amountCoin: "",
    direction: "in",
    reason: "admin_adjust",
};

const defaultPolicyForm = {
    enabled: true,
    protectionRounds: 30,
    protectionHours: 168,
    maxStakeCoin: 5000,
    lifetimeSubsidyQuotaCoin: 30000,
    day1SubsidyQuotaCoin: 15000,
    singleRoundSubsidyCapCoin: 5000,
    strategyLevel: "soft_boost",
    loseStreakProtectionEnabled: true,
    loseStreakTrigger: 2,
    normalPhaseTargetWinRatePercent: 53,
    blackPoolRobotForceWinEnabled: false,
};

export function SelfGamePage() {
    const { can } = useAuth();
    const { showToast } = useToast();
    const canUpdate = can(PERMISSIONS.gameUpdate);
    const [items, setItems] = useState([]);
    const [loading, setLoading] = useState(true);
    const [loadingAction, setLoadingAction] = useState("");
    const [activeAction, setActiveAction] = useState("");
    const [activeGame, setActiveGame] = useState(null);
    const [configForm, setConfigForm] = useState(defaultConfigForm);
    const [stakePools, setStakePools] = useState([]);
    const [stakePoolConfigForm, setStakePoolConfigForm] = useState(defaultStakePoolConfigForm);
    const [stakePoolAdjustForm, setStakePoolAdjustForm] = useState(defaultStakePoolAdjustForm);
    const [policyForm, setPolicyForm] = useState(defaultPolicyForm);

    const load = useCallback(async () => {
        setLoading(true);
        try {
            const result = await listSelfGames();
            setItems(result.items || []);
        } catch (err) {
            showToast(err.message || "加载自研游戏失败", "error");
        } finally {
            setLoading(false);
        }
    }, [showToast]);

    useEffect(() => {
        load();
    }, [load]);

    const closeDialog = useCallback(() => {
        setActiveAction("");
        setActiveGame(null);
    }, []);

    const openConfig = useCallback((game) => {
        setActiveGame(game);
        setConfigForm(configToForm(game));
        setActiveAction("config");
    }, []);

    const applyStakePools = useCallback((pools, direction = "in") => {
        const items = pools || [];
        setStakePools(items);
        const selected = items[0];
        if (!selected) {
            setStakePoolConfigForm(defaultStakePoolConfigForm);
            setStakePoolAdjustForm({ ...defaultStakePoolAdjustForm, direction });
            return;
        }
        setStakePoolConfigForm(stakePoolToConfigForm(selected));
        setStakePoolAdjustForm(stakePoolToAdjustForm(selected, direction));
    }, []);

    const reloadStakePools = useCallback(
        async (gameId, direction = stakePoolAdjustForm.direction || "in") => {
            const result = await listSelfGameStakePools(gameId);
            applyStakePools(result.items || [], direction);
        },
        [applyStakePools, stakePoolAdjustForm.direction],
    );

    const openStakePools = useCallback(
        async (game, direction = "in") => {
            setActiveGame(game);
            setActiveAction("stake-pools");
            setLoadingAction("stake-pools-load");
            try {
                await reloadStakePools(game.gameId, direction);
            } catch (err) {
                showToast(err.message || "加载档位奖池失败", "error");
                closeDialog();
            } finally {
                setLoadingAction("");
            }
        },
        [closeDialog, reloadStakePools, showToast],
    );

    const openPolicy = useCallback(
        async (game) => {
            setActiveGame(game);
            setPolicyForm({ ...defaultPolicyForm, gameId: game.gameId });
            setActiveAction("policy");
            setLoadingAction("policy-load");
            try {
                const policy = await getSelfGameNewUserPolicy(game.gameId);
                setPolicyForm(policyToForm(policy, game.gameId));
            } catch (err) {
                showToast(err.message || "加载新手策略失败", "error");
                closeDialog();
            } finally {
                setLoadingAction("");
            }
        },
        [closeDialog, showToast],
    );

    const columns = useMemo(
        () => [
            {
                key: "game",
                label: "游戏",
                width: "minmax(180px, 1.2fr)",
                render: (game) => (
                    <div className={styles.identity}>
                        <span className={styles.name}>{game.gameId === "dice" ? "骰子" : game.gameId}</span>
                        <span className={styles.meta}>{game.gameId}</span>
                    </div>
                ),
            },
            {
                key: "stakes",
                label: "下注档位",
                width: "minmax(220px, 1.4fr)",
                render: (game) => game.stakeOptions.map((item) => formatNumber(item.stakeCoin)).join(" / "),
            },
            {
                key: "fee",
                label: "费率",
                width: "minmax(140px, .8fr)",
                render: (game) => `${bpsPercent(game.feeBps)} / 入池 ${bpsPercent(game.poolBps)}`,
            },
            {
                key: "pool",
                label: "奖池",
                width: "minmax(120px, .8fr)",
                render: (game) => formatNumber(game.poolBalanceCoin),
            },
            {
                key: "robot",
                label: "机器人",
                width: "minmax(190px, .9fr)",
                render: (game) => `${game.robotEnabled ? "启用" : "关闭"} · ${game.robotMatchWaitMs}ms · 策略引擎`,
            },
            {
                key: "updated",
                label: "更新时间",
                width: "minmax(170px, 1fr)",
                render: (game) => (game.updatedAtMs ? formatMillis(game.updatedAtMs) : "-"),
            },
            {
                key: "actions",
                label: "操作",
                width: "232px",
                render: (game) => (
                    <AdminRowActions>
                        <AdminActionIconButton disabled={!canUpdate} label="配置骰子" onClick={() => openConfig(game)}>
                            <SettingsOutlined fontSize="small" />
                        </AdminActionIconButton>
                        <AdminActionIconButton disabled={!canUpdate} label="新手策略" onClick={() => openPolicy(game)}>
                            <TuneOutlined fontSize="small" />
                        </AdminActionIconButton>
                        <AdminActionIconButton
                            disabled={!canUpdate}
                            label="档位奖池"
                            onClick={() => openStakePools(game, "in")}
                        >
                            <AccountBalanceWalletOutlined fontSize="small" />
                        </AdminActionIconButton>
                        <AdminActionIconButton
                            disabled={!canUpdate}
                            label="快速加奖池"
                            onClick={() => openStakePools(game, "in")}
                        >
                            <AddCircleOutlineOutlined fontSize="small" />
                        </AdminActionIconButton>
                    </AdminRowActions>
                ),
            },
        ],
        [canUpdate, openConfig, openPolicy, openStakePools],
    );

    const submitConfig = async (event) => {
        event.preventDefault();
        if (!activeGame) return;
        setLoadingAction("config");
        try {
            await updateDiceConfig(activeGame.gameId, configPayload(configForm, activeGame.gameId));
            await load();
            showToast("骰子配置已保存", "success");
            closeDialog();
        } catch (err) {
            showToast(err.message || "保存骰子配置失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    const submitStakePoolConfig = async (event) => {
        event.preventDefault();
        if (!activeGame) return;
        setLoadingAction("stake-pool-config");
        try {
            await updateSelfGameStakePool(
                activeGame.gameId,
                Number(stakePoolConfigForm.stakeCoin || 0),
                stakePoolConfigPayload(stakePoolConfigForm),
            );
            await reloadStakePools(activeGame.gameId, stakePoolAdjustForm.direction || "in");
            showToast("档位奖池配置已保存", "success");
        } catch (err) {
            showToast(err.message || "保存档位奖池失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    const submitStakePoolAdjust = async (event) => {
        event.preventDefault();
        if (!activeGame) return;
        setLoadingAction("stake-pool-adjust");
        try {
            await adjustSelfGameStakePool(activeGame.gameId, Number(stakePoolAdjustForm.stakeCoin || 0), {
                amountCoin: Number(stakePoolAdjustForm.amountCoin || 0),
                direction: stakePoolAdjustForm.direction,
                reason: stakePoolAdjustForm.reason,
            });
            await load();
            await reloadStakePools(activeGame.gameId, stakePoolAdjustForm.direction || "in");
            setStakePoolAdjustForm((current) => ({ ...current, amountCoin: "" }));
            showToast(stakePoolAdjustForm.direction === "out" ? "档位奖池已扣除" : "档位奖池已增加", "success");
        } catch (err) {
            showToast(err.message || "调整档位奖池失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    const submitPolicy = async (event) => {
        event.preventDefault();
        if (!activeGame) return;
        setLoadingAction("policy");
        try {
            await updateSelfGameNewUserPolicy(activeGame.gameId, policyPayload(policyForm, activeGame.gameId));
            await load();
            showToast("新手策略已保存", "success");
            closeDialog();
        } catch (err) {
            showToast(err.message || "保存新手策略失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    if (loading) {
        return <PageSkeleton />;
    }

    return (
        <AdminListPage>
            <AdminListToolbar
                actions={
                    <AdminActionIconButton label="刷新" onClick={load}>
                        <RefreshOutlined fontSize="small" />
                    </AdminActionIconButton>
                }
            />
            <AdminListBody>
                <DataTable columns={columns} items={items} minWidth="980px" rowKey={(game) => game.gameId} />
            </AdminListBody>
            <ConfigDialog
                form={configForm}
                loading={loadingAction === "config"}
                open={activeAction === "config"}
                setForm={setConfigForm}
                onClose={closeDialog}
                onSubmit={submitConfig}
            />
            <StakePoolsDialog
                adjustForm={stakePoolAdjustForm}
                configForm={stakePoolConfigForm}
                loading={loadingAction === "stake-pools-load" || loadingAction === "stake-pool-config"}
                pools={stakePools}
                setAdjustForm={setStakePoolAdjustForm}
                setConfigForm={setStakePoolConfigForm}
                submittingConfig={loadingAction === "stake-pool-config"}
                submittingAdjust={loadingAction === "stake-pool-adjust"}
                open={activeAction === "stake-pools"}
                onClose={closeDialog}
                onSubmitAdjust={submitStakePoolAdjust}
                onSubmitConfig={submitStakePoolConfig}
            />
            <PolicyDialog
                form={policyForm}
                loading={loadingAction === "policy" || loadingAction === "policy-load"}
                open={activeAction === "policy"}
                setForm={setPolicyForm}
                onClose={closeDialog}
                onSubmit={submitPolicy}
            />
        </AdminListPage>
    );
}

function ConfigDialog({ form, loading, open, setForm, onClose, onSubmit }) {
    return (
        <AdminFormDialog
            loading={loading}
            open={open}
            submitLabel="保存配置"
            title="骰子配置"
            onClose={onClose}
            onSubmit={onSubmit}
        >
            <AdminFormSection title="下注与费率">
                <AdminFormFieldGrid>
                    <TextField
                        label="下注档位"
                        value={form.stakeOptionsText}
                        onChange={(event) => setForm({ ...form, stakeOptionsText: event.target.value })}
                    />
                    <TextField
                        label="平台抽水 bps"
                        type="number"
                        value={form.feeBps}
                        onChange={(event) => setForm({ ...form, feeBps: event.target.value })}
                    />
                    <TextField
                        label="入池 bps"
                        type="number"
                        value={form.poolBps}
                        onChange={(event) => setForm({ ...form, poolBps: event.target.value })}
                    />
                    <TextField
                        label="状态"
                        select
                        value={form.status}
                        onChange={(event) => setForm({ ...form, status: event.target.value })}
                    >
                        <MenuItem value="active">启用</MenuItem>
                        <MenuItem value="disabled">停用</MenuItem>
                    </TextField>
                </AdminFormFieldGrid>
            </AdminFormSection>
            <AdminFormSection title="匹配">
                <AdminFormFieldGrid>
                    <TextField
                        label="最少人数"
                        type="number"
                        value={form.minPlayers}
                        onChange={(event) => setForm({ ...form, minPlayers: event.target.value })}
                    />
                    <TextField
                        label="最多人数"
                        type="number"
                        value={form.maxPlayers}
                        onChange={(event) => setForm({ ...form, maxPlayers: event.target.value })}
                    />
                    <TextField
                        label="机器人等待 ms"
                        type="number"
                        value={form.robotMatchWaitMs}
                        onChange={(event) => setForm({ ...form, robotMatchWaitMs: event.target.value })}
                    />
                    <AdminFormSwitchField
                        checked={form.robotEnabled}
                        label="机器人补位"
                        onChange={(checked) => setForm({ ...form, robotEnabled: checked })}
                    />
                </AdminFormFieldGrid>
            </AdminFormSection>
        </AdminFormDialog>
    );
}

function StakePoolsDialog({
    adjustForm,
    configForm,
    loading,
    open,
    pools,
    setAdjustForm,
    setConfigForm,
    submittingAdjust,
    submittingConfig,
    onClose,
    onSubmitAdjust,
    onSubmitConfig,
}) {
    const selectedStakeCoin = Number(configForm.stakeCoin || adjustForm.stakeCoin || 0);
    const selectedPool = pools.find((pool) => pool.stakeCoin === selectedStakeCoin) || pools[0];
    const isDeduct = adjustForm.direction === "out";
    const selectPool = (pool, direction = adjustForm.direction || "in") => {
        setConfigForm(stakePoolToConfigForm(pool));
        setAdjustForm(stakePoolToAdjustForm(pool, direction));
    };
    return (
        <AdminFormDialog
            loading={loading}
            open={open}
            size="wide"
            submitDisabled={loading || submittingConfig || !configForm.stakeCoin}
            submitLabel="保存档位配置"
            title="档位奖池"
            onClose={onClose}
            onSubmit={onSubmitConfig}
        >
            <AdminFormSection title="档位水位">
                <div className={styles.stakePoolList}>
                    {pools.length ? (
                        pools.map((pool) => (
                            <button
                                key={pool.stakeCoin}
                                className={[
                                    styles.stakePoolRow,
                                    pool.stakeCoin === selectedStakeCoin ? styles.stakePoolRowActive : "",
                                ]
                                    .filter(Boolean)
                                    .join(" ")}
                                type="button"
                                onClick={() => selectPool(pool)}
                            >
                                <span className={styles.stakePoolMain}>
                                    <span className={styles.stakePoolStake}>{formatNumber(pool.stakeCoin)}</span>
                                    <span className={poolLevelClass(pool.poolLevel)}>
                                        {poolLevelText(pool.poolLevel)}
                                    </span>
                                </span>
                                <span className={styles.stakePoolMetrics}>
                                    余额 {formatNumber(pool.balanceCoin)} · 可用 {formatNumber(pool.availableCoin)} ·
                                    冻结 {formatNumber(pool.reservedCoin)}
                                </span>
                                <span className={styles.stakePoolMetrics}>
                                    单局需 {formatNumber(pool.requiredPoolCoin)} · 可承受{" "}
                                    {formatNumber(pool.humanWinCapacity)} 次 ·{" "}
                                    {pool.botMatchEnabled ? "可补机器人" : "暂停补机器人"}
                                </span>
                                {pool.poolLevel === "black" ? (
                                    <span className={styles.stakePoolWarning}>
                                        黑色原因：{blackReasonText(pool.blackReason)}
                                    </span>
                                ) : null}
                            </button>
                        ))
                    ) : (
                        <div className={styles.stakePoolEmpty}>暂无档位奖池</div>
                    )}
                </div>
            </AdminFormSection>
            <AdminFormSection title="水位阈值">
                <AdminFormFieldGrid>
                    <TextField disabled label="当前档位" value={formatNumber(configForm.stakeCoin)} />
                    <TextField
                        label="状态"
                        select
                        value={configForm.status}
                        onChange={(event) => setConfigForm({ ...configForm, status: event.target.value })}
                    >
                        <MenuItem value="active">启用</MenuItem>
                        <MenuItem value="disabled">停用</MenuItem>
                    </TextField>
                    <TextField
                        label="目标奖池"
                        type="number"
                        value={configForm.targetBalanceCoin}
                        slotProps={{ htmlInput: { min: 0 } }}
                        onChange={(event) => setConfigForm({ ...configForm, targetBalanceCoin: event.target.value })}
                    />
                    <TextField
                        label="绿色阈值"
                        type="number"
                        value={configForm.safeBalanceCoin}
                        slotProps={{ htmlInput: { min: 0 } }}
                        onChange={(event) => setConfigForm({ ...configForm, safeBalanceCoin: event.target.value })}
                    />
                    <TextField
                        label="黄色阈值"
                        type="number"
                        value={configForm.warningBalanceCoin}
                        slotProps={{ htmlInput: { min: 0 } }}
                        onChange={(event) => setConfigForm({ ...configForm, warningBalanceCoin: event.target.value })}
                    />
                    <TextField
                        label="红色阈值"
                        type="number"
                        value={configForm.dangerBalanceCoin}
                        slotProps={{ htmlInput: { min: 0 } }}
                        onChange={(event) => setConfigForm({ ...configForm, dangerBalanceCoin: event.target.value })}
                    />
                </AdminFormFieldGrid>
                {selectedPool ? (
                    <div className={styles.stakePoolHint}>
                        黑色水位自动判断：状态停用，或可用余额低于单局需 {formatNumber(selectedPool.requiredPoolCoin)}。
                    </div>
                ) : null}
            </AdminFormSection>
            <AdminFormSection title="档位奖池加扣">
                <AdminFormFieldGrid>
                    <TextField disabled label="当前档位" value={formatNumber(adjustForm.stakeCoin)} />
                    <TextField
                        label="方向"
                        select
                        value={adjustForm.direction}
                        onChange={(event) =>
                            setAdjustForm({
                                ...adjustForm,
                                direction: event.target.value,
                                reason: event.target.value === "out" ? "admin_deduct" : "admin_adjust",
                            })
                        }
                    >
                        <MenuItem value="in">增加</MenuItem>
                        <MenuItem value="out">扣除</MenuItem>
                    </TextField>
                    <TextField
                        helperText={isDeduct ? "不能扣成负数" : ""}
                        label="金币"
                        type="number"
                        value={adjustForm.amountCoin}
                        slotProps={{ htmlInput: { min: 1 } }}
                        onChange={(event) => setAdjustForm({ ...adjustForm, amountCoin: event.target.value })}
                    />
                    <TextField
                        label="原因"
                        value={adjustForm.reason}
                        onChange={(event) => setAdjustForm({ ...adjustForm, reason: event.target.value })}
                    />
                </AdminFormFieldGrid>
                <div className={styles.stakePoolInlineActions}>
                    <button
                        className={styles.stakePoolPrimaryButton}
                        disabled={loading || submittingAdjust || !adjustForm.stakeCoin || !adjustForm.amountCoin}
                        type="button"
                        onClick={onSubmitAdjust}
                    >
                        {isDeduct ? "确认扣除" : "确认增加"}
                    </button>
                </div>
            </AdminFormSection>
        </AdminFormDialog>
    );
}

function StrategyLevelLabel() {
    return (
        <span className={styles.strategyLevelLabel}>
            <span>策略等级</span>
            <HelpOutlineOutlined className={styles.strategyLevelHelpIcon} fontSize="inherit" />
        </span>
    );
}

function StrategyLevelTooltip() {
    return (
        <div className={styles.strategyLevelTooltip}>
            <div className={styles.strategyLevelTooltipTitle}>只影响新手期机器人补位局</div>
            <div>
                低风险、绿色水位、下注 1000/5000 且额度足够时：柔性激励按第 1 局 70%、第 2-6 局 60%、第 7-16 局 55%、第
                17-30 局 50%、第 31 局后正常随机；强激励对应 85%、75%、65%、55%、50%。
            </div>
            <ul className={styles.strategyLevelTooltipList}>
                <li>关闭保护：不强制用户赢，全部走 dice/rock 正常随机。</li>
                <li>首局不输：第 1 个有效机器人局 100% 正反馈，后续按柔性激励曲线。</li>
                <li>柔性激励案例：第 3 个有效机器人局命中率 60%；rock 平局不计有效局，也不消耗额度。</li>
                <li>强激励案例：第 10 个有效机器人局命中率 65%；第 20 个有效机器人局命中率 55%。</li>
                <li>黄色水位案例：柔性第 1 局 70% 降到 60%，强激励第 1 局 85% 降到 75%。</li>
                <li>风控案例：risk_score 30-49 降 10%，50-69 降 25%，70 及以上不享受保护。</li>
                <li>额度案例：默认最大下注 5000，40000/100000 档不触发；首日额度不足时降级正常随机。</li>
                <li>自然期案例：配置 50% 就完全自然随机；配置 53% 时 dice 约 6% 的机器人局补正为用户赢，rock 约 4.1%。</li>
            </ul>
        </div>
    );
}

function PolicyDialog({ form, loading, open, setForm, onClose, onSubmit }) {
    return (
        <AdminFormDialog
            loading={loading}
            open={open}
            submitLabel="保存策略"
            title="新手策略"
            onClose={onClose}
            onSubmit={onSubmit}
        >
            <AdminFormSection title="保护窗口">
                <AdminFormFieldGrid>
                    <AdminFormSwitchField
                        checked={form.enabled}
                        label="启用"
                        onChange={(checked) => setForm({ ...form, enabled: checked })}
                    />
                    <Tooltip
                        arrow
                        placement="left"
                        title={<StrategyLevelTooltip />}
                        slotProps={{ tooltip: { className: styles.strategyLevelTooltipPaper } }}
                    >
                        <TextField
                            label={<StrategyLevelLabel />}
                            select
                            value={form.strategyLevel}
                            onChange={(event) => setForm({ ...form, strategyLevel: event.target.value })}
                        >
                            <MenuItem value="none">关闭保护</MenuItem>
                            <MenuItem value="first_no_lose">首局不输</MenuItem>
                            <MenuItem value="soft_boost">柔性激励</MenuItem>
                            <MenuItem value="strong_boost">强激励</MenuItem>
                        </TextField>
                    </Tooltip>
                    <TextField
                        label="保护局数"
                        type="number"
                        value={form.protectionRounds}
                        slotProps={{ htmlInput: { min: 1 } }}
                        onChange={(event) => setForm({ ...form, protectionRounds: event.target.value })}
                    />
                    <TextField
                        label="保护小时"
                        type="number"
                        value={form.protectionHours}
                        slotProps={{ htmlInput: { min: 1 } }}
                        onChange={(event) => setForm({ ...form, protectionHours: event.target.value })}
                    />
                </AdminFormFieldGrid>
            </AdminFormSection>
            <AdminFormSection title="补贴额度">
                <AdminFormFieldGrid>
                    <TextField
                        label="最大下注"
                        type="number"
                        value={form.maxStakeCoin}
                        slotProps={{ htmlInput: { min: 1 } }}
                        onChange={(event) => setForm({ ...form, maxStakeCoin: event.target.value })}
                    />
                    <TextField
                        label="生命周期额度"
                        type="number"
                        value={form.lifetimeSubsidyQuotaCoin}
                        slotProps={{ htmlInput: { min: 1 } }}
                        onChange={(event) => setForm({ ...form, lifetimeSubsidyQuotaCoin: event.target.value })}
                    />
                    <TextField
                        label="首日额度"
                        type="number"
                        value={form.day1SubsidyQuotaCoin}
                        slotProps={{ htmlInput: { min: 1 } }}
                        onChange={(event) => setForm({ ...form, day1SubsidyQuotaCoin: event.target.value })}
                    />
                    <TextField
                        label="单局上限"
                        type="number"
                        value={form.singleRoundSubsidyCapCoin}
                        slotProps={{ htmlInput: { min: 1 } }}
                        onChange={(event) => setForm({ ...form, singleRoundSubsidyCapCoin: event.target.value })}
                    />
                </AdminFormFieldGrid>
            </AdminFormSection>
            <AdminFormSection title="连输保护">
                <AdminFormFieldGrid>
                    <AdminFormSwitchField
                        checked={form.loseStreakProtectionEnabled}
                        label="启用"
                        onChange={(checked) => setForm({ ...form, loseStreakProtectionEnabled: checked })}
                    />
                    <TextField
                        label="连输阈值"
                        type="number"
                        value={form.loseStreakTrigger}
                        slotProps={{ htmlInput: { min: 1 } }}
                        onChange={(event) => setForm({ ...form, loseStreakTrigger: event.target.value })}
                    />
                </AdminFormFieldGrid>
            </AdminFormSection>
            <AdminFormSection title="成熟期体验">
                <AdminFormFieldGrid>
                    <Tooltip
                        arrow
                        placement="left"
                        title="只影响已过新手保护候选条件的机器人补位局。50% 表示完全自然随机；高于 50% 会换算成少量用户赢补正，不会强制用户输，也不消耗新手补贴额度。"
                    >
                        <TextField
                            helperText="建议 53，用来抵消 5% 平台费和 1% 入池带来的长期负期望"
                            label="自然期目标胜率 %"
                            type="number"
                            value={form.normalPhaseTargetWinRatePercent}
                            slotProps={{ htmlInput: { min: 50, max: 100, step: 1 } }}
                            onChange={(event) => setForm({ ...form, normalPhaseTargetWinRatePercent: event.target.value })}
                        />
                    </Tooltip>
                </AdminFormFieldGrid>
            </AdminFormSection>
            <AdminFormSection title="黑色水位">
                <AdminFormFieldGrid>
                    <Tooltip arrow placement="left" title="关闭时黑色档位只等待真人；开启时黑色档位允许机器人补位，并强制机器人获胜。">
                        <AdminFormSwitchField
                            checked={form.blackPoolRobotForceWinEnabled}
                            label="机器人强制获胜"
                            onChange={(checked) => setForm({ ...form, blackPoolRobotForceWinEnabled: checked })}
                        />
                    </Tooltip>
                </AdminFormFieldGrid>
            </AdminFormSection>
        </AdminFormDialog>
    );
}

function configToForm(game) {
    return {
        status: game.status || "active",
        stakeOptionsText: (game.stakeOptions || []).map((item) => item.stakeCoin).join(","),
        feeBps: game.feeBps,
        poolBps: game.poolBps,
        minPlayers: game.minPlayers,
        maxPlayers: game.maxPlayers,
        robotEnabled: game.robotEnabled,
        robotMatchWaitMs: game.robotMatchWaitMs,
    };
}

function configPayload(form, gameId) {
    return {
        gameId,
        status: form.status,
        stakeOptions: parseStakeOptions(form.stakeOptionsText),
        feeBps: Number(form.feeBps || 0),
        poolBps: Number(form.poolBps || 0),
        minPlayers: Number(form.minPlayers || 2),
        maxPlayers: Number(form.maxPlayers || 2),
        robotEnabled: Boolean(form.robotEnabled),
        robotMatchWaitMs: Number(form.robotMatchWaitMs || 3000),
    };
}

function policyToForm(policy, gameId) {
    return {
        ...defaultPolicyForm,
        ...policy,
        gameId,
    };
}

function policyPayload(form, gameId) {
    return {
        gameId,
        enabled: Boolean(form.enabled),
        protectionRounds: Number(form.protectionRounds || 30),
        protectionHours: Number(form.protectionHours || 168),
        maxStakeCoin: Number(form.maxStakeCoin || 5000),
        lifetimeSubsidyQuotaCoin: Number(form.lifetimeSubsidyQuotaCoin || 30000),
        day1SubsidyQuotaCoin: Number(form.day1SubsidyQuotaCoin || 15000),
        singleRoundSubsidyCapCoin: Number(form.singleRoundSubsidyCapCoin || 5000),
        strategyLevel: form.strategyLevel || "soft_boost",
        loseStreakProtectionEnabled: Boolean(form.loseStreakProtectionEnabled),
        loseStreakTrigger: Number(form.loseStreakTrigger || 2),
        normalPhaseTargetWinRatePercent: Number(form.normalPhaseTargetWinRatePercent || 53),
        blackPoolRobotForceWinEnabled: Boolean(form.blackPoolRobotForceWinEnabled),
    };
}

function stakePoolToConfigForm(pool) {
    if (!pool) return defaultStakePoolConfigForm;
    return {
        stakeCoin: pool.stakeCoin,
        targetBalanceCoin: pool.targetBalanceCoin,
        safeBalanceCoin: pool.safeBalanceCoin,
        warningBalanceCoin: pool.warningBalanceCoin,
        dangerBalanceCoin: pool.dangerBalanceCoin,
        status: pool.status || "active",
    };
}

function stakePoolToAdjustForm(pool, direction = "in") {
    if (!pool) return { ...defaultStakePoolAdjustForm, direction };
    return {
        ...defaultStakePoolAdjustForm,
        stakeCoin: pool.stakeCoin,
        direction,
        reason: direction === "out" ? "admin_deduct" : "admin_adjust",
    };
}

function stakePoolConfigPayload(form) {
    return {
        targetBalanceCoin: Number(form.targetBalanceCoin || 0),
        safeBalanceCoin: Number(form.safeBalanceCoin || 0),
        warningBalanceCoin: Number(form.warningBalanceCoin || 0),
        dangerBalanceCoin: Number(form.dangerBalanceCoin || 0),
        status: form.status || "active",
    };
}

function poolLevelText(level) {
    switch (level) {
        case "green":
            return "绿色";
        case "yellow":
            return "黄色";
        case "red":
            return "红色";
        case "black":
            return "黑色";
        default:
            return level || "-";
    }
}

function poolLevelClass(level) {
    return [styles.poolLevelBadge, styles[`poolLevel_${level || "unknown"}`]].filter(Boolean).join(" ");
}

function blackReasonText(reason) {
    switch (reason) {
        case "status_disabled":
            return "档位奖池已停用";
        case "available_below_required_pool_coin":
            return "可用余额不足以覆盖真人赢机器人净支出";
        default:
            return reason || "可用余额不足";
    }
}

function parseStakeOptions(text) {
    return String(text || "")
        .split(/[,，\s]+/)
        .map((value) => Number(value))
        .filter((value) => Number.isFinite(value) && value > 0)
        .map((stakeCoin, index) => ({ stakeCoin, enabled: true, sortOrder: (index + 1) * 10 }));
}

function bpsPercent(value) {
    return `${(Number(value || 0) / 100).toFixed(2)}%`;
}

function formatNumber(value) {
    return new Intl.NumberFormat("en-US").format(Number(value || 0));
}
