import FormControlLabel from "@mui/material/FormControlLabel";
import MenuItem from "@mui/material/MenuItem";
import TextField from "@mui/material/TextField";
import { useEffect, useMemo, useRef, useState } from "react";
import { AdminSwitch } from "@/shared/ui/AdminSwitch.jsx";
import { LuckyGiftFieldLabel } from "./LuckyGiftFieldHelp.jsx";

const BASE_SECTIONS = [
    ["identity", "规则"],
    ["funds", "资金"],
];

const DYNAMIC_SECTIONS = [
    ["water", "水位"],
    ["jackpot", "大奖"],
    ["limits", "限额"],
];

export function LuckyGiftConfigSections({
    appOptions,
    experimentMode = false,
    form,
    hostDiamondRatioAvailable = true,
    isCreate,
    onChange,
}) {
    const scrollRef = useRef(null);
    const sections = useMemo(
        () => (form.strategy_version === "dynamic_v3" ? [...BASE_SECTIONS, ...DYNAMIC_SECTIONS] : BASE_SECTIONS),
        [form.strategy_version],
    );
    const [activeSection, setActiveSection] = useState(sections[0][0]);

    useEffect(() => {
        if (sections.some(([sectionKey]) => sectionKey === activeSection)) return;
        // dynamic_v3 的专属分区会在切回 fixed_v2 后卸载；同步回首个有效分区，避免导航继续指向不存在的面板。
        setActiveSection(sections[0][0]);
        if (scrollRef.current) resolveConfigScroller(scrollRef.current).scrollTop = 0;
    }, [activeSection, sections]);

    useEffect(() => {
        const sectionList = scrollRef.current;
        if (!sectionList) return undefined;
        const view = sectionList.ownerDocument.defaultView;
        let boundScroller;

        const syncActiveSection = () => {
            if (!boundScroller) return;
            const readingLine =
                boundScroller.getBoundingClientRect().top + configNavInset(sectionList, boundScroller) + 32;
            let nextSection = sections[0][0];
            for (const [sectionKey] of sections) {
                const section = sectionList.querySelector(`[data-config-section="${sectionKey}"]`);
                if (section && section.getBoundingClientRect().top <= readingLine) nextSection = sectionKey;
            }
            setActiveSection((current) => (current === nextSection ? current : nextSection));
        };

        const bindActualScroller = () => {
            const nextScroller = resolveConfigScroller(sectionList);
            if (nextScroller === boundScroller) return;
            boundScroller?.removeEventListener("scroll", syncActiveSection);
            boundScroller = nextScroller;
            // 桌面由参数面板独立滚动，平板/手机由 DialogContent 单滚动；只监听真实 scroller，
            // 避免小屏内层 overflow:visible 时导航状态更新、内容位置却完全没有变化。
            boundScroller.addEventListener("scroll", syncActiveSection, { passive: true });
        };

        bindActualScroller();
        view?.addEventListener("resize", bindActualScroller);
        const ResizeObserverClass = view?.ResizeObserver;
        const resizeObserver = ResizeObserverClass ? new ResizeObserverClass(bindActualScroller) : null;
        resizeObserver?.observe(sectionList);

        return () => {
            boundScroller?.removeEventListener("scroll", syncActiveSection);
            view?.removeEventListener("resize", bindActualScroller);
            resizeObserver?.disconnect();
        };
    }, [sections]);

    const jumpToSection = (sectionKey) => {
        const sectionList = scrollRef.current;
        const section = sectionList?.querySelector(`[data-config-section="${sectionKey}"]`);
        if (!sectionList || !section) return;
        const scroller = resolveConfigScroller(sectionList);
        setActiveSection(sectionKey);
        // offsetParent 不是可靠的滚动参考系；无论当前是桌面内层还是响应式外层滚动，都用视口坐标
        // 换算同一个 scroller 的目标位点；窄屏横向导航是 sticky 覆盖层，目标还必须落到导航下方。
        const navInset = configNavInset(sectionList, scroller);
        const top = Math.max(
            scroller.scrollTop +
                section.getBoundingClientRect().top -
                scroller.getBoundingClientRect().top -
                navInset -
                8,
            0,
        );
        const reduceMotion = scroller.ownerDocument.defaultView?.matchMedia?.(
            "(prefers-reduced-motion: reduce)",
        ).matches;
        if (typeof scroller.scrollTo === "function") {
            scroller.scrollTo({ behavior: reduceMotion ? "auto" : "smooth", top });
        } else {
            // jsdom 和部分旧 WebView 没有 Element.scrollTo，直接写 scrollTop 仍能保持导航可用。
            scroller.scrollTop = top;
        }
        // 导航按钮只负责选择分区；焦点落到标题后，读屏会立即获得当前编辑上下文。
        section.querySelector("h3")?.focus({ preventScroll: true });
    };

    const fundTotal =
        Number(form.pool_rate_percent || 0) +
        Number(form.profit_rate_percent || 0) +
        Number(form.anchor_rate_percent || 0);

    return (
        <aside className="ops-config-params" aria-label="全局参数">
            <nav className="ops-config-section-nav" aria-label="全局参数分区">
                <strong>全局参数</strong>
                {sections.map(([sectionKey, label]) => (
                    <button
                        aria-controls={`ops-config-section-${sectionKey}`}
                        aria-current={activeSection === sectionKey ? "true" : undefined}
                        className={activeSection === sectionKey ? "is-active" : ""}
                        key={sectionKey}
                        type="button"
                        onClick={() => jumpToSection(sectionKey)}
                    >
                        {label}
                    </button>
                ))}
            </nav>

            <div className="ops-config-section-list" ref={scrollRef}>
                <section
                    aria-labelledby="ops-config-heading-identity"
                    className="ops-config-section"
                    data-config-section="identity"
                    id="ops-config-section-identity"
                >
                    <SectionHeading id="ops-config-heading-identity" title="规则身份" />
                    <div className="ops-form-grid">
                        {isCreate ? (
                            <TextField
                                fullWidth
                                required
                                label={<LuckyGiftFieldLabel field="app_code" label="应用" />}
                                select
                                size="small"
                                value={form.app_code}
                                onChange={(event) => onChange("app_code", event.target.value)}
                            >
                                {appOptions.map(([value, label]) => (
                                    <MenuItem key={value} value={value}>
                                        {label}
                                    </MenuItem>
                                ))}
                            </TextField>
                        ) : (
                            <TextField
                                disabled
                                fullWidth
                                label={<LuckyGiftFieldLabel field="app_code" label="应用" />}
                                size="small"
                                value={form.app_code}
                            />
                        )}
                        <TextField
                            // 实验绑定当前行的 app+pool（对照组由该奖池最新启用版本担任）；
                            // 实验模式下改奖池 ID 会把实验开到另一个奖池家族，必须锁定。
                            disabled={experimentMode}
                            fullWidth
                            required
                            label={<LuckyGiftFieldLabel field="pool_id" label="奖池" />}
                            size="small"
                            value={form.pool_id}
                            onChange={(event) => onChange("pool_id", event.target.value)}
                        />
                        <TextField
                            // 奖池身份仍被实验锁定，但策略属于每个不可变规则版本；开放选择才能直接对照
                            // fixed_v2 与 dynamic_v3。切换策略时由表单归一化清理另一代策略的专属字段。
                            fullWidth
                            label={<LuckyGiftFieldLabel field="strategy_version" label="策略版本" />}
                            select
                            size="small"
                            value={form.strategy_version}
                            onChange={(event) => onChange("strategy_version", event.target.value)}
                        >
                            <MenuItem value="dynamic_v3">dynamic_v3</MenuItem>
                            <MenuItem value="fixed_v2">fixed_v2（历史兼容）</MenuItem>
                        </TextField>
                        <FormControlLabel
                            className="ops-config-enabled-field"
                            control={
                                <AdminSwitch
                                    checked={form.enabled}
                                    // 实验组配置发布后立即参与分流开奖，owner 拒绝停用的实验组；
                                    // 创建实验时锁定启用开关，避免运营误以为可以先停用再放量。
                                    disabled={experimentMode}
                                    label="发布状态"
                                    onChange={(event) => onChange("enabled", event.target.checked)}
                                />
                            }
                            label={
                                <LuckyGiftFieldLabel
                                    field="enabled"
                                    label={
                                        experimentMode
                                            ? "实验组配置直接参与开奖"
                                            : form.enabled
                                              ? "发布后立即启用"
                                              : "发布后保持停用"
                                    }
                                />
                            }
                        />
                    </div>
                    <p className="ops-field-note">
                        {experimentMode
                            ? "对照组保持当前版本；实验组可选择 fixed_v2 或 dynamic_v3。"
                            : "修改奖池 ID 会发布到新奖池，不影响原奖池。"}
                    </p>
                </section>

                <section
                    aria-labelledby="ops-config-heading-funds"
                    className="ops-config-section"
                    data-config-section="funds"
                    id="ops-config-section-funds"
                >
                    <SectionHeading
                        detail={
                            form.strategy_version === "dynamic_v3"
                                ? `资金合计 ${formatCompactNumber(fundTotal)}%`
                                : undefined
                        }
                        id="ops-config-heading-funds"
                        ok={Math.abs(fundTotal - 100) < 0.0001}
                        title="返奖与资金分配"
                    />
                    <div className="ops-form-grid">
                        <NumberField
                            form={form}
                            label="目标 RTP (%)"
                            name="target_rtp_percent"
                            step="0.01"
                            onChange={onChange}
                        />
                        <NumberField
                            form={form}
                            label="奖档允许偏差 (%)"
                            name="control_band_percent"
                            step="0.01"
                            onChange={onChange}
                        />
                        <NumberField
                            form={form}
                            label="进入奖池比例 (%)"
                            name="pool_rate_percent"
                            step="0.01"
                            onChange={onChange}
                        />
                        <NumberField
                            form={form}
                            label="平台收入比例 (%)"
                            name="profit_rate_percent"
                            step="0.01"
                            onChange={onChange}
                        />
                        <NumberField
                            form={form}
                            label="每轮观察流水"
                            name="settlement_window_wager"
                            onChange={onChange}
                        />
                        <NumberField
                            form={form}
                            label="V2 折算参考单价"
                            name="gift_price_reference"
                            onChange={onChange}
                        />
                        <NumberField
                            disabled={form.strategy_version === "dynamic_v3"}
                            form={form}
                            label="新手阶段上限（折算次数）"
                            name="novice_max_equivalent_draws"
                            onChange={onChange}
                        />
                        <NumberField
                            disabled={form.strategy_version === "dynamic_v3"}
                            form={form}
                            label="普通阶段上限（折算次数）"
                            name="normal_max_equivalent_draws"
                            onChange={onChange}
                        />
                    </div>
                    {form.strategy_version === "dynamic_v3" ? (
                        <p className="ops-field-note">
                            {hostDiamondRatioAvailable
                                ? `主播钻石比例由礼物配置读取，当前为 ${formatCompactNumber(Number(form.anchor_rate_percent || 0))}%；本页不提供修改。`
                                : "未读取到当前应用的主播钻石比例，刷新成功前不能发布 V3 配置。"}
                        </p>
                    ) : (
                        <>
                            <div className="ops-form-grid">
                                <NumberField
                                    form={form}
                                    label="高水位加权阈值（金币）"
                                    name="v2_high_water_boost_threshold_coins"
                                    required={false}
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="高水位加权系数 (%)"
                                    name="v2_high_water_boost_factor_percent"
                                    required={false}
                                    step="0.01"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="加权恢复水位（金币）"
                                    name="v2_high_water_boost_recover_coins"
                                    required={false}
                                    onChange={onChange}
                                />
                            </div>
                            <p className="ops-field-note">
                                V2 高水位加权：奖池水位越过阈值后，中奖返奖按系数放大（150 表示 RTP 变为原来的
                                150%），直到水位跌破恢复水位才恢复正常；阈值填 0 表示关闭。
                            </p>
                        </>
                    )}
                </section>

                {form.strategy_version === "dynamic_v3" ? (
                    <>
                        <section
                            aria-labelledby="ops-config-heading-water"
                            className="ops-config-section"
                            data-config-section="water"
                            id="ops-config-section-water"
                        >
                            <SectionHeading id="ops-config-heading-water" title="动态水位" />
                            <div className="ops-form-grid">
                                <NumberField
                                    disabled
                                    form={form}
                                    helperText="请通过奖池水位操作注资"
                                    label="初始奖池金币"
                                    name="initial_pool_coins"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="连续未中奖保护次数"
                                    name="loss_streak_guarantee"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="低水位金币"
                                    name="low_watermark_coins"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="低余额中奖权重 (%)"
                                    name="low_water_nonzero_factor_percent"
                                    step="0.01"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="高水位金币"
                                    name="high_watermark_coins"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="高余额中奖权重 (%)"
                                    name="high_water_nonzero_factor_percent"
                                    step="0.01"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="充值加权窗口 (ms)"
                                    name="recharge_boost_window_ms"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="充值后中奖权重 (%)"
                                    name="recharge_boost_factor_percent"
                                    step="0.01"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="用户近 24 小时 RTP 触发线 (%)"
                                    name="user_24h_rtp_threshold_percent"
                                    step="0.01"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="高 RTP 时普通中奖机会保留 (%)"
                                    name="user_24h_ordinary_win_factor_percent"
                                    step="0.01"
                                    onChange={onChange}
                                />
                            </div>
                        </section>

                        <section
                            aria-labelledby="ops-config-heading-jackpot"
                            className="ops-config-section"
                            data-config-section="jackpot"
                            id="ops-config-section-jackpot"
                        >
                            <SectionHeading id="ops-config-heading-jackpot" title="独立大奖路径" />
                            <div className="ops-jackpot-rule-groups">
                                <JackpotRuleGroup
                                    description="两种大奖策略都先检查大盘：实际 RTP 小于或等于配置上限才通过，等于也通过；还必须有足够奖池水位并同时通过全部返奖限额。每日大奖次数由两种策略合并计算，同一子抽最多发出一个大奖。"
                                    id="ops-jackpot-shared-heading"
                                    title="共享开奖前提"
                                >
                                    <div className="ops-form-grid">
                                        <TextField
                                            className="ops-form-grid__wide"
                                            helperText="按从小到大填写；可与普通奖档使用相同倍率"
                                            label={
                                                <LuckyGiftFieldLabel
                                                    field="jackpot_multipliers"
                                                    label="独立大奖倍率（可选倍数）"
                                                />
                                            }
                                            required
                                            size="small"
                                            value={form.jackpot_multipliers}
                                            onChange={(event) => onChange("jackpot_multipliers", event.target.value)}
                                        />
                                        <NumberField
                                            form={form}
                                            label="全局大奖 RTP 上限 (%)"
                                            name="jackpot_global_rtp_max_percent"
                                            step="0.01"
                                            onChange={onChange}
                                        />
                                        <NumberField
                                            form={form}
                                            label="每位用户每日独立大奖总次数"
                                            name="max_jackpot_hits_per_user_day"
                                            onChange={onChange}
                                        />
                                    </div>
                                </JackpotRuleGroup>

                                <JackpotRuleGroup
                                    description="大盘结算时，用户必须注册满 48 小时，并且本轮 RTP 与近 48 小时总 RTP 都严格低于各自触发线。两项缺一不可；资格只尝试一次。与消费策略同时有资格时，本策略先尝试：成功后消费资格留到下一子抽，未出奖则同一子抽继续尝试消费资格。"
                                    id="ops-jackpot-rtp-heading"
                                    title="48 小时亏损补偿"
                                >
                                    <div className="ops-form-grid">
                                        <NumberField
                                            form={form}
                                            label="用户本轮返还触发线 (%)"
                                            name="jackpot_user_round_rtp_max_percent"
                                            step="0.01"
                                            onChange={onChange}
                                        />
                                        <NumberField
                                            form={form}
                                            label="用户近 48 小时返还触发线 (%)"
                                            name="jackpot_user_48h_rtp_max_percent"
                                            step="0.01"
                                            onChange={onChange}
                                        />
                                    </div>
                                </JackpotRuleGroup>

                                <JackpotRuleGroup
                                    description="同一应用、奖池和用户按 UTC 自然日累计实际消费，每满一次门槛就产生 1 个大奖资格。资格从下一子抽开始尝试；批量送礼中本次达标，下一子抽即可使用。大盘、水位、次数或限额不通过时资格会跨日保留，直到成功支付；它与 48 小时策略独立，不要求注册满 48 小时，也不检查用户 RTP。"
                                    id="ops-jackpot-spend-heading"
                                    title="累计消费达标"
                                >
                                    <div className="ops-form-grid">
                                        <NumberField
                                            form={form}
                                            helperText="每个 UTC 自然日每满一次门槛，产生 1 个待用资格"
                                            label="用户日累计消费触发门槛（金币）"
                                            name="jackpot_spend_threshold_coins"
                                            onChange={onChange}
                                        />
                                    </div>
                                </JackpotRuleGroup>
                            </div>
                        </section>

                        <section
                            aria-labelledby="ops-config-heading-limits"
                            className="ops-config-section"
                            data-config-section="limits"
                            id="ops-config-section-limits"
                        >
                            <SectionHeading id="ops-config-heading-limits" title="各场景返奖上限" />
                            <div className="ops-form-grid">
                                <NumberField
                                    form={form}
                                    label="单次返奖上限"
                                    name="max_single_payout"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="每位用户每小时最高返奖"
                                    name="user_hourly_payout_cap"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="每位用户每日最高返奖"
                                    name="user_daily_payout_cap"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="每台设备每日最高返奖"
                                    name="device_daily_payout_cap"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="每个房间每小时最高返奖"
                                    name="room_hourly_payout_cap"
                                    onChange={onChange}
                                />
                                <NumberField
                                    form={form}
                                    label="主播每日上限"
                                    name="anchor_daily_payout_cap"
                                    onChange={onChange}
                                />
                            </div>
                        </section>
                    </>
                ) : null}
            </div>
        </aside>
    );
}

function SectionHeading({ detail, id, ok = false, title }) {
    return (
        <div className="ops-config-section__head">
            <h3 id={id} tabIndex={-1}>
                {title}
            </h3>
            {detail ? <span className={ok ? "is-ok" : "is-warn"}>{detail}</span> : null}
        </div>
    );
}

function JackpotRuleGroup({ children, description, id, title }) {
    return (
        <section aria-labelledby={id} className="ops-jackpot-rule-group">
            <div className="ops-jackpot-rule-group__head">
                <h4 id={id}>{title}</h4>
                <p>{description}</p>
            </div>
            {children}
        </section>
    );
}

function NumberField({ disabled = false, form, helperText, label, name, onChange, required = true, step = "1" }) {
    return (
        <TextField
            disabled={disabled}
            helperText={helperText}
            label={<LuckyGiftFieldLabel field={name} label={label} />}
            required={required}
            size="small"
            slotProps={{ htmlInput: { inputMode: "decimal", min: 0, step } }}
            type="number"
            value={form[name]}
            onChange={(event) => onChange(name, event.target.value)}
        />
    );
}

function formatCompactNumber(value) {
    return Number.isFinite(value) ? Number(value.toFixed(4)).toString() : "-";
}

function resolveConfigScroller(sectionList) {
    // 桌面参数列限定高度后由自己滚动；响应式规则把它改为 overflow:visible，此时 scrollHeight 与
    // clientHeight 相等，实际滚动责任上移到 DialogContent。判定能力而非 viewport 宽度可兼容缩放和嵌入场景。
    if (sectionList.scrollHeight > sectionList.clientHeight) return sectionList;
    return sectionList.closest(".ops-config-dialog-content") || sectionList;
}

function configNavInset(sectionList, scroller) {
    if (scroller === sectionList) return 0;
    const nav = sectionList.previousElementSibling;
    if (!nav?.classList.contains("ops-config-section-nav")) return 0;
    // 响应式是否形成覆盖层由真实布局决定：390px 时 nav 为横向 row，1024px 时仍是左侧 column。
    // 读取 computed style 而不是猜 innerWidth，才能兼容浏览器缩放、嵌入容器和未来断点调整。
    const flexDirection = nav.ownerDocument.defaultView?.getComputedStyle(nav).flexDirection;
    return flexDirection === "row" ? nav.getBoundingClientRect().height : 0;
}
