import Skeleton from "@mui/material/Skeleton";
import { Button } from "@/shared/ui/Button.jsx";
import { TimeText } from "@/shared/ui/TimeText.jsx";
import { formatMultiplierFromPPM, formatNumber, formatPercentFromPPM } from "../format.js";
import { OpsStatusBadge } from "./OpsStatusBadge.jsx";

export function UserProfileDetail({ detailState, onLoadMore, onRetry, profile }) {
    return (
        <div className="admin-row ops-user-profile-detail-row">
            <div className="ops-user-profile-detail-cell">
                {!detailState || detailState.loading ? <DetailSkeleton /> : null}
                {detailState?.error ? (
                    <div className="ops-user-profile-detail-error" role="alert">
                        <span>{detailState.error}</span>
                        <Button size="small" onClick={onRetry}>
                            重试
                        </Button>
                    </div>
                ) : null}
                {detailState?.data && !detailState.loading ? (
                    <ProfileDetailContent
                        data={detailState.data}
                        fallbackProfile={profile}
                        loadingMore={detailState.loadingMore}
                        onLoadMore={onLoadMore}
                    />
                ) : null}
            </div>
        </div>
    );
}

function ProfileDetailContent({ data, fallbackProfile, loadingMore, onLoadMore }) {
    const profile = data.profile?.key ? data.profile : fallbackProfile;
    const distribution = [...(data.multiplierDistribution || [])].sort(
        (left, right) => right.multiplierPpm - left.multiplierPpm,
    );
    const jackpotHits = data.jackpotHits || [];

    return (
        <div className="ops-user-profile-detail">
            <section className="ops-user-profile-detail__summary" aria-label="用户控制状态详情">
                <DetailMetric label="最近开奖阶段" value={stageLabel(profile.stage)} />
                <DetailMetric label="连续未中奖" value={`${formatNumber(profile.lossStreak)} 次`} />
                <DetailMetric label="等价抽数" value={formatNumber(profile.equivalentDraws)} />
                <DetailMetric
                    label="保底状态"
                    value={
                        profile.guaranteeDrawsRemaining > 0
                            ? `还差 ${formatNumber(profile.guaranteeDrawsRemaining)} 抽`
                            : "保护剩余 0 抽"
                    }
                />
                <DetailMetric
                    label="24 小时降权"
                    value={
                        profile.downweightActive
                            ? `已触发，普通中奖保留 ${formatPercentFromPPM(profile.user24hOrdinaryWinFactorPpm)}`
                            : "未触发"
                    }
                />
                <DetailMetric label="待兑消费大奖" value={`${formatNumber(profile.pendingCumulativeSpendTokens)} 次`} />
                <DetailMetric label="累计有效抽数" value={`${formatNumber(profile.paidDraws)} 抽`} />
                <DetailMetric label="基础返奖" value={`${formatNumber(profile.baseRewardCoins)} 金币`} />
                <DetailMetric label="保底命中" value={`${formatNumber(profile.guaranteeHitCount)} 次`} />
                <DetailMetric
                    label="历史最高单次"
                    value={`${formatMultiplierFromPPM(profile.maxMultiplierPpm)} / ${formatNumber(profile.maxRewardCoins)} 金币`}
                />
                <DetailMetric label="首次抽奖" value={<TimeText value={profile.firstDrawAtMs} />} />
                <DetailMetric
                    label="处理结果"
                    value={`已发 ${formatNumber(profile.grantedDrawCount)} / 待处理 ${formatNumber(
                        profile.pendingDrawCount,
                    )} / 失败 ${formatNumber(profile.failedDrawCount)}`}
                />
            </section>

            <section className="ops-user-profile-detail__section">
                <header>
                    <div>
                        <h3>倍率命中分布</h3>
                        <p>普通随机和两条大奖通道分列，倍率相同时也不会混为一次命中。</p>
                    </div>
                    <span>{distribution.length} 个倍率</span>
                </header>
                {distribution.length ? (
                    <div className="ops-profile-multiplier-table">
                        <div className="ops-profile-multiplier-row is-head">
                            <span>倍率</span>
                            <span>未中奖</span>
                            <span>普通命中</span>
                            <span>RTP 补偿大奖</span>
                            <span>累计消费大奖</span>
                            <span>合计命中</span>
                            <span>返奖金币</span>
                        </div>
                        {distribution.map((metric) => (
                            <div className="ops-profile-multiplier-row" key={metric.multiplierPpm}>
                                <strong>{formatMultiplierFromPPM(metric.multiplierPpm)}</strong>
                                <span>{formatNumber(metric.zeroDrawCount)}</span>
                                <span>{formatNumber(metric.ordinaryHitCount)}</span>
                                <span>{formatNumber(metric.rtpCompensationJackpotCount)}</span>
                                <span>{formatNumber(metric.cumulativeSpendJackpotCount)}</span>
                                <span>{formatNumber(metric.hitCount)}</span>
                                <span>{formatNumber(metric.payoutCoins)}</span>
                            </div>
                        ))}
                    </div>
                ) : (
                    <div className="ops-user-profile-detail__empty">当前没有倍率命中数据</div>
                )}
            </section>

            <section className="ops-user-profile-detail__section">
                <header>
                    <div>
                        <h3>大奖命中依据</h3>
                        <p>逐次展示走哪条大奖通道、命中时的关键门槛和实际判断结果。</p>
                    </div>
                    <span>
                        展示 {jackpotHits.length} / 共 {formatNumber(data.jackpotHitTotal || jackpotHits.length)} 次
                    </span>
                </header>
                {jackpotHits.length ? (
                    <>
                        <div className="ops-profile-jackpot-list">
                            {jackpotHits.map((hit, index) => (
                                <JackpotHit
                                    hit={hit}
                                    key={hit.eventKey || `${hit.drawId}:${hit.requestId}:${hit.occurredAtMs}:${index}`}
                                />
                            ))}
                        </div>
                        {data.jackpotHasMore && data.nextJackpotCursor ? (
                            <div className="ops-profile-jackpot-more">
                                <Button disabled={loadingMore} onClick={onLoadMore} size="small">
                                    {loadingMore ? "加载中…" : "加载更早的大奖记录"}
                                </Button>
                            </div>
                        ) : null}
                    </>
                ) : (
                    <div className="ops-user-profile-detail__empty">该用户当前没有大奖命中记录</div>
                )}
            </section>
        </div>
    );
}

function DetailMetric({ label, value }) {
    return (
        <dl>
            <dt>{label}</dt>
            <dd>{value || "-"}</dd>
        </dl>
    );
}

function JackpotHit({ hit }) {
    const conditions = flattenConditions(hit.conditions);
    const mechanism = mechanismLabel(hit.mechanism);
    return (
        <article className="ops-profile-jackpot-hit">
            <div className="ops-profile-jackpot-hit__head">
                <div>
                    <OpsStatusBadge label={mechanism} tone={mechanismTone(hit.mechanism)} />
                    <strong>{formatMultiplierFromPPM(hit.multiplierPpm)}</strong>
                    <span>返奖 {formatNumber(hit.payoutCoins)} 金币</span>
                </div>
                <TimeText value={hit.occurredAtMs} />
            </div>
            <div className="ops-profile-jackpot-hit__reason">
                <strong>为什么命中</strong>
                <span>{reasonLabel(hit.reason, hit.reasonCode, hit.mechanism)}</span>
            </div>
            {conditions.length ? (
                <dl className="ops-profile-jackpot-conditions">
                    {conditions.map((condition) => (
                        <div key={condition.key}>
                            <dt>{condition.value?.label || conditionLabel(condition.key)}</dt>
                            <dd>{conditionValue(condition.key, condition.value)}</dd>
                        </div>
                    ))}
                </dl>
            ) : (
                <div className="ops-profile-jackpot-hit__no-conditions">该历史记录没有保存更多判断快照</div>
            )}
            <footer>
                <span>阶段：{stageLabel(hit.stage)}</span>
                <span>规则：v{hit.ruleVersion || "-"}</span>
                <span>消耗：{formatNumber(hit.wagerCoins)} 金币</span>
                {hit.tierId ? <span>奖档：{hit.tierId}</span> : null}
                {hit.drawId ? <span>抽奖单：{hit.drawId}</span> : null}
                {hit.requestId ? <span>请求号：{hit.requestId}</span> : null}
            </footer>
        </article>
    );
}

function DetailSkeleton() {
    return (
        <div className="ops-user-profile-detail-skeleton" aria-hidden="true">
            <div>
                {Array.from({ length: 6 }, (_, index) => (
                    <Skeleton animation="wave" height={42} key={index} variant="rounded" />
                ))}
            </div>
            <Skeleton animation="wave" height={112} variant="rounded" />
            <Skeleton animation="wave" height={156} variant="rounded" />
        </div>
    );
}

function flattenConditions(value, prefix = "") {
    if (Array.isArray(value)) {
        return value
            .filter((condition) => condition && !isInternalIdentityKey(condition.name))
            .map((condition, index) => ({
                key: condition.name || `condition_${index + 1}`,
                value: condition,
            }));
    }
    if (!value || typeof value !== "object") {
        return [];
    }
    return Object.entries(value).flatMap(([key, child]) => {
        const path = prefix ? `${prefix}.${key}` : key;
        // stable hash、strategy user key 等仅用于 owner 内部关联，尤其外部用户不能从诊断快照泄露。
        if (isInternalIdentityKey(path)) {
            return [];
        }
        if (child && typeof child === "object" && !Array.isArray(child)) {
            return flattenConditions(child, path);
        }
        return [{ key: path, value: Array.isArray(child) ? child.join("、") : child }];
    });
}

function isInternalIdentityKey(key) {
    const normalized = String(key).toLowerCase();
    return ["strategy_user_id", "user_key", "stable_user", "hashed_user", "user_hash"].some((token) =>
        normalized.includes(token),
    );
}

function mechanismLabel(mechanism) {
    const normalized = String(mechanism || "").toLowerCase();
    if (["rtp_compensation", "mechanism_1", "jackpot_mechanism_1", "compensation"].includes(normalized)) {
        return "RTP 补偿大奖";
    }
    if (["cumulative_spend", "spend_milestone", "mechanism_2", "jackpot_mechanism_2", "spend"].includes(normalized)) {
        return "累计消费大奖";
    }
    return mechanism || "大奖";
}

function mechanismTone(mechanism) {
    return mechanismLabel(mechanism) === "累计消费大奖" ? "warning" : "succeeded";
}

function reasonLabel(reason, reasonCode, mechanism) {
    const normalized = String(reason || "").trim();
    const known = {
        cumulative_spend_token_redeemed: "累计消费达到门槛后生成大奖机会，本抽满足支付条件并完成兑付。",
        jackpot_token_redeemed: "此前生成的大奖机会在本抽满足支付条件并完成兑付。",
        milestone_token_jackpot: "用户累计消费已获得一次大奖机会，且奖池余额足够支付，因此触发累计消费大奖。",
        rtp_compensation_eligible: "用户和全局 RTP 等补偿条件均满足，本抽进入 RTP 补偿大奖通道并命中。",
        rtp_compensation_jackpot: "用户与奖池均满足补偿条件，且奖池余额足够支付，因此触发 RTP 补偿大奖。",
        rtp_compensation_token_redeemed: "RTP 补偿机会已生成，本抽满足奖池支付条件并完成兑付。",
    };
    const normalizedCode = String(reasonCode || "")
        .trim()
        .toLowerCase();
    if (known[normalizedCode] || known[normalized.toLowerCase()] || normalized) {
        return known[normalizedCode] || known[normalized.toLowerCase()] || normalized;
    }
    return mechanismLabel(mechanism) === "累计消费大奖"
        ? "累计消费达到规则门槛，生成的大奖机会在本抽完成兑付。"
        : "用户和全局 RTP、奖池水位等门槛均允许，RTP 补偿机会在本抽完成兑付。";
}

function conditionLabel(key) {
    const normalized = String(key).split(".").pop()?.toLowerCase() || key;
    const labels = {
        pool_balance_coins: "命中前奖池余额",
        pool_payable: "奖池能否支付",
        global_rtp_ppm: "命中前全局 RTP",
        global_rtp_max_ppm: "全局 RTP 上限",
        user_24h_rtp_ppm: "命中前用户 24 小时 RTP",
        user_48h_rtp_ppm: "命中前用户 48 小时 RTP",
        user_48h_rtp_max_ppm: "用户 48 小时 RTP 上限",
        user_round_rtp_ppm: "命中前用户本轮 RTP",
        user_round_rtp_max_ppm: "用户本轮 RTP 上限",
        daily_hit_count: "当日已中大奖次数",
        daily_hit_limit: "单日大奖次数上限",
        cumulative_spend_coins: "累计消费金币",
        cumulative_spend_threshold_coins: "累计消费门槛",
        pending_token_count: "命中前待兑大奖机会",
        multiplier_ppm: "命中倍率",
        stage: "命中阶段",
        eligible: "是否满足条件",
        allowed: "是否允许发放",
    };
    return labels[normalized] || humanizeConditionKey(normalized);
}

function conditionValue(key, value) {
    if (value && typeof value === "object" && !Array.isArray(value)) {
        const parts = [];
        const hasFriendlyValues = Boolean(value.actual || value.threshold);
        if (hasFriendlyValues) {
            parts.push(
                [value.actual ? `实际 ${value.actual}` : "", operatorLabel(value.operator), value.threshold || ""]
                    .filter(Boolean)
                    .join(" "),
            );
        }
        if (!hasFriendlyValues && value.denominator > 0) {
            parts.push(`${formatNumber(value.numerator)} / ${formatNumber(value.denominator)}`);
        }
        if (!hasFriendlyValues && (value.ratioPpm || value.limitPpm)) {
            parts.push(`实际 ${formatPercentFromPPM(value.ratioPpm)} / 门槛 ${formatPercentFromPPM(value.limitPpm)}`);
        }
        if (value.factorPpm) {
            parts.push(`权重 ${formatPercentFromPPM(value.factorPpm)}`);
        }
        parts.push(value.passed ? "通过" : "未通过");
        if (value.reason) {
            parts.push(value.reason);
        }
        return parts.join(" · ");
    }
    const normalized = String(key).toLowerCase();
    if (typeof value === "boolean") {
        return value ? "是" : "否";
    }
    if (value === null || value === undefined || value === "") {
        return "-";
    }
    if (normalized.endsWith("_ppm") || normalized.includes("rtp_ppm")) {
        return formatPercentFromPPM(value);
    }
    if (normalized.endsWith("_coins") || normalized.includes("count") || normalized.includes("limit")) {
        return formatNumber(value);
    }
    return String(value);
}

function operatorLabel(value) {
    const labels = {
        eq: "等于",
        gt: "高于",
        gte: "不低于",
        lt: "低于",
        lte: "不高于",
    };
    const normalized = String(value || "")
        .trim()
        .toLowerCase();
    return labels[normalized] || value || "";
}

function humanizeConditionKey(key) {
    return String(key)
        .replaceAll("_", " ")
        .replace(/\bRtp\b/gi, "RTP")
        .replace(/\bPpm\b/gi, "百分比")
        .replace(/\bCoins\b/gi, "金币");
}

function stageLabel(stage) {
    const normalized = String(stage || "").toLowerCase();
    if (["novice", "newbie", "new"].includes(normalized)) {
        return "新手阶段";
    }
    if (["normal", "ordinary"].includes(normalized)) {
        return "普通阶段";
    }
    if (["advanced", "high", "high_value", "premium"].includes(normalized)) {
        return "高价阶段";
    }
    return stage || "未记录";
}
