import AddOutlined from "@mui/icons-material/AddOutlined";
import { useMemo, useState } from "react";
import { AdminFilterSelect, AdminListToolbar } from "@/shared/ui/AdminListLayout.jsx";
import { Button } from "@/shared/ui/Button.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import { TimeText } from "@/shared/ui/TimeText.jsx";
import { luckyGiftPoolKey } from "../api.js";
import { activeExperimentsByPool, experimentPoolFamilyKey, experimentStatusBadge } from "../experimentForm.js";
import { formatNumber, formatPercent } from "../format.js";
import { LuckyGiftPoolActions } from "./LuckyGiftPoolActions.jsx";
import { OpsStatusBadge } from "./OpsStatusBadge.jsx";

export function ConfigsView({
    apps,
    canCredit,
    canDebit,
    canExperiment,
    canUpdate,
    disabled,
    experiments,
    luckyGifts,
    onCreate,
    onCreateExperiment,
    onCredit,
    onDebit,
    onEdit,
    onManageExperiment,
    onRollback,
    poolBalances,
    saving,
}) {
    const [appFilter, setAppFilter] = useState("");

    const appOptions = useMemo(
        () =>
            apps.map((item) => [
                item.app_code ?? item.appCode,
                `${item.app_name ?? item.appName ?? ""} (${item.app_code ?? item.appCode})`,
            ]),
        [apps],
    );
    // 配置列表已在 dashboard 阶段跨应用拉全，应用筛选只做前端过滤，避免重复扇出请求。
    const items = useMemo(() => {
        const poolByKey = new Map(poolBalances.map((pool) => [luckyGiftPoolKey(pool), pool]));
        // 实验按 app+pool 独占且不区分策略版本：同一奖池的 fixed_v2 / dynamic_v3 两行
        // 共享同一个活跃实验的徽章与发布封锁，因此这里用 family key 而不是 luckyGiftPoolKey。
        const experimentByPool = activeExperimentsByPool(experiments);
        const visibleConfigs = appFilter ? luckyGifts.filter((config) => config.app_code === appFilter) : luckyGifts;
        // 余额必须按 app+pool+strategy 精确关联；同一个 app/pool 同时存在 fixed_v2 和 dynamic_v3 时，
        // 任何缺少 strategy_version 的关联都会把两口独立资金池串行或覆盖。
        return visibleConfigs.map((config) => ({
            ...config,
            active_experiment: experimentByPool.get(experimentPoolFamilyKey(config)) || null,
            pool_balance: poolByKey.get(luckyGiftPoolKey(config)),
        }));
    }, [appFilter, experiments, luckyGifts, poolBalances]);

    // 实验详情入口对仅有查看权限的账号同样开放（后端 GET 只要求 lucky-gift:view），
    // 操作列宽度必须把这类行算进去，否则视图权限账号的实验行按钮会溢出。
    const hasExperimentEntry = canExperiment || items.some((item) => item.active_experiment);

    const columns = useMemo(
        () =>
            buildColumns({
                canCredit,
                canDebit,
                canExperiment,
                canUpdate,
                disabled,
                hasExperimentEntry,
                onCreateExperiment,
                onCredit,
                onDebit,
                onEdit,
                onManageExperiment,
                onRollback,
                saving,
            }),
        [
            canCredit,
            canDebit,
            canExperiment,
            canUpdate,
            disabled,
            hasExperimentEntry,
            onCreateExperiment,
            onCredit,
            onDebit,
            onEdit,
            onManageExperiment,
            onRollback,
            saving,
        ],
    );

    return (
        <div className="ops-view">
            <AdminListToolbar
                actions={
                    canUpdate ? (
                        <Button
                            disabled={saving}
                            startIcon={<AddOutlined fontSize="small" />}
                            variant="primary"
                            onClick={onCreate}
                        >
                            添加配置
                        </Button>
                    ) : null
                }
                filters={
                    <AdminFilterSelect
                        label="应用"
                        options={[["", "全部应用"], ...appOptions]}
                        value={appFilter}
                        onChange={setAppFilter}
                    />
                }
            />
            <DataTable
                columns={columns}
                emptyLabel="暂无幸运礼物配置"
                items={items}
                minWidth="1540px"
                rowKey={(item) => `${luckyGiftPoolKey(item)}:${item.rule_version}`}
                title="幸运礼物配置"
                total={items.length}
            />
        </div>
    );
}

function buildColumns({
    canCredit,
    canDebit,
    canExperiment,
    canUpdate,
    disabled,
    hasExperimentEntry,
    onCreateExperiment,
    onCredit,
    onDebit,
    onEdit,
    onManageExperiment,
    onRollback,
    saving,
}) {
    const columns = [
        { key: "app_code", label: "应用", width: "minmax(88px, 0.7fr)" },
        { key: "pool_id", label: "奖池", width: "minmax(110px, 0.9fr)" },
        {
            key: "rule_version",
            label: "版本",
            render: (item) => (item.is_default ? "-" : `v${item.rule_version}`),
            width: "minmax(72px, 0.5fr)",
        },
        {
            key: "strategy_version",
            label: "策略",
            // 升级前的不可变版本可能没有该字段，owner 会按 fixed_v2 解释；列表保持同一兼容口径，
            // 不能把空值展示成 dynamic_v3，避免运营误判已完成策略切换。
            render: (item) => item.strategy_version || "fixed_v2",
            width: "minmax(112px, 0.8fr)",
        },
        {
            key: "pool_balance",
            label: "奖池余额",
            render: (item) => (item.pool_balance ? formatNumber(item.pool_balance.balance) : "-"),
            width: "minmax(120px, 0.9fr)",
        },
        {
            key: "enabled",
            label: "状态",
            render: (item) => {
                // 默认草稿是服务端为未配置奖池生成的占位，不参与线上抽奖，必须与"停用"区分开。
                if (item.is_default) {
                    return <OpsStatusBadge label="默认草稿" tone="warning" />;
                }
                return item.enabled ? (
                    <OpsStatusBadge label="已启用" tone="succeeded" />
                ) : (
                    <OpsStatusBadge label="已停用" />
                );
            },
            width: "minmax(128px, 0.8fr)",
        },
        {
            key: "experiment",
            label: "实验",
            render: (item) => {
                // 只展示活跃实验（running/paused）；completed 实验已全量收敛，不再影响该行的发布能力。
                const badge = experimentStatusBadge(item.active_experiment);
                return badge ? <OpsStatusBadge label={badge.label} tone={badge.tone} /> : "-";
            },
            width: "minmax(120px, 0.8fr)",
        },
        { key: "target_rtp_percent", label: "目标 RTP", render: (item) => formatPercent(item.target_rtp_percent) },
        { key: "pool_rate_percent", label: "公共奖池", render: (item) => formatPercent(item.pool_rate_percent) },
        {
            key: "profit_anchor_rate",
            label: "平台 / 主播",
            render: (item) => `${formatPercent(item.profit_rate_percent)} / ${formatPercent(item.anchor_rate_percent)}`,
            width: "minmax(144px, 1fr)",
        },
        { key: "control_band_percent", label: "控制带宽", render: (item) => formatPercent(item.control_band_percent) },
        {
            key: "settlement_window_wager",
            label: "结算窗口流水",
            render: (item) => formatNumber(item.settlement_window_wager),
        },
        {
            key: "created_at_ms",
            label: "发布时间",
            render: (item) => (item.is_default ? "-" : <TimeText value={item.created_at_ms} />),
            width: "minmax(176px, 1.1fr)",
        },
    ];

    if (canUpdate || canCredit || canDebit || hasExperimentEntry) {
        columns.push({
            fixed: "right",
            key: "actions",
            label: "操作",
            render: (item) => {
                const identity = `${item.app_code} / ${item.pool_id} / ${item.strategy_version}`;
                const hasActiveExperiment = Boolean(item.active_experiment);
                const actionPool = item.pool_balance || {
                    app_code: item.app_code,
                    pool_id: item.pool_id,
                    strategy_version: item.strategy_version,
                };
                return (
                    <div className="ops-config-actions">
                        <LuckyGiftPoolActions
                            canCredit={canCredit}
                            canDebit={canDebit}
                            disabled={disabled}
                            pool={actionPool}
                            onCredit={onCredit}
                            onDebit={onDebit}
                        />
                        {canUpdate ? (
                            <Button
                                aria-label={`${item.is_default ? "发布配置" : "新增版本"} ${identity}`}
                                // 活跃实验独占该奖池的版本发布（owner 对常规 PUT 返回 409）；
                                // 前端直接禁用入口并说明原因，而不是让运营提交后才看到冲突报错。
                                disabled={saving || hasActiveExperiment}
                                size="small"
                                title={hasActiveExperiment ? "实验进行中，结束实验后才能发布" : undefined}
                                onClick={() => onEdit(item)}
                            >
                                {item.is_default ? "发布配置" : "新增版本"}
                            </Button>
                        ) : null}
                        {canUpdate && !item.is_default ? (
                            <Button
                                aria-label={`回滚版本 ${identity}`}
                                // 回滚同样会发布一个新版本，必须服从实验对奖池的发布独占约束。
                                disabled={saving || hasActiveExperiment}
                                size="small"
                                title={hasActiveExperiment ? "实验进行中，结束实验后才能回滚" : undefined}
                                onClick={() => onRollback(item)}
                            >
                                回滚版本
                            </Button>
                        ) : null}
                        {hasActiveExperiment ? (
                            <Button
                                aria-label={`实验详情 ${identity}`}
                                disabled={saving}
                                size="small"
                                variant="primary"
                                onClick={() => onManageExperiment(item.active_experiment)}
                            >
                                实验详情
                            </Button>
                        ) : canExperiment && item.enabled && !item.is_default ? (
                            // 只有已启用的已发布配置才能作为对照组开实验；默认草稿/停用行没有可对照的线上版本。
                            <Button
                                aria-label={`创建 AB 实验 ${identity}`}
                                disabled={saving}
                                size="small"
                                onClick={() => onCreateExperiment(item)}
                            >
                                创建 AB 实验
                            </Button>
                        ) : null}
                    </div>
                );
            },
            width: `${
                (canCredit ? 110 : 0) +
                (canDebit ? 110 : 0) +
                (canUpdate ? 220 : 0) +
                (hasExperimentEntry ? 128 : 0) +
                20
            }px`,
        });
    }

    return columns;
}
