import PlayArrowOutlined from "@mui/icons-material/PlayArrowOutlined";
import Checkbox from "@mui/material/Checkbox";
import Tab from "@mui/material/Tab";
import Tabs from "@mui/material/Tabs";
import { useEffect, useMemo, useState } from "react";
import {
    listHostSalarySettlements,
    listHostSalarySettlementPending,
    listTeamSalarySettlementPending,
    listTeamSalarySettlementRecords,
    settleHostSalary,
    settleTeamSalary,
} from "@/features/host-agency-policy/api";
import { useHostAgencyPolicyAbilities } from "@/features/host-agency-policy/permissions.js";
import { useCountryOptions } from "@/features/host-org/hooks/useCountryOptions.js";
import { useRegionOptions } from "@/shared/hooks/useRegionOptions.js";
import {
    AdminFilterResetButton,
    AdminFilterSelect,
    AdminListBody,
    AdminListPage,
    AdminListToolbar,
} from "@/shared/ui/AdminListLayout.jsx";
import { AdminUserIdentity } from "@/shared/ui/AdminUserIdentity.jsx";
import { Button } from "@/shared/ui/Button.jsx";
import { DataState } from "@/shared/ui/DataState.jsx";
import { DataTable } from "@/shared/ui/DataTable.jsx";
import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js";
import { TimeRangeFilter } from "@/shared/ui/TimeRangeFilter.jsx";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import { createOptionsColumnFilter, createTextColumnFilter, createUserIdentityColumnFilter } from "@/shared/ui/tableFilters.js";
import {
    emptyUserIdentityFilter,
    isUserIdentityFilterEmpty,
    userIdentityFilterParams,
} from "@/shared/ui/userIdentityFilter.js";
import { formatMillis } from "@/shared/utils/time.js";
import styles from "@/features/host-agency-policy/host-agency-policy.module.css";

const pageSize = 50;

const settlementTypeOptions = [
    ["", "全部类型"],
    ["daily", "日结"],
    ["half_month", "半月结算"],
    ["month_end", "月底清算"],
];

const statusOptions = [
    ["", "全部状态"],
    ["succeeded", "成功"],
    ["skipped", "跳过"],
    ["failed", "失败"],
];

const policyTypeOptions = [
    ["bd", "BD"],
    ["admin", "Admin"],
];

const policyTypeAllOptions = [["", "全部角色"], ...policyTypeOptions];

const pendingRoleOptions = [
    ["bd", "BD"],
    ["admin", "Admin"],
    ["host", "Host"],
    ["agency", "Agency"],
];

const triggerOptions = [
    ["automatic", "自动政策"],
    ["manual", "手动政策"],
];

const triggerAllOptions = [["", "全部触发"], ...triggerOptions];

export function HostSalarySettlementPage() {
    const [activeTab, setActiveTab] = useState("pending");
    return (
        <AdminListPage>
            <div className={styles.policyTabsBar}>
                <Tabs value={activeTab} onChange={(_, value) => setActiveTab(value)}>
                    <Tab className={styles.policyTab} label="待结算" value="pending" />
                    <Tab className={styles.policyTab} label="BD/Admin 记录" value="team-records" />
                    <Tab className={styles.policyTab} label="Host/Agency 记录" value="host-records" />
                </Tabs>
            </div>
            {activeTab === "pending" ? (
                <PendingPanel />
            ) : activeTab === "team-records" ? (
                <TeamRecordsPanel />
            ) : (
                <HostRecordsPanel />
            )}
        </AdminListPage>
    );
}

function PendingPanel() {
    const [role, setRole] = useState("bd");
    if (role === "host" || role === "agency") {
        return <HostPendingPanel role={role} onRoleChange={setRole} />;
    }
    return <TeamPendingPanel role={role} onRoleChange={setRole} />;
}

// HostPendingPanel 展示 Host/Agency 动态账单；列表查询不入账，点击结算后才让 wallet-service 写钱包和记录。
function HostPendingPanel({ onRoleChange, role }) {
    const abilities = useHostAgencyPolicyAbilities();
    const { showToast } = useToast();
    const { countryOptions, loadingCountries } = useCountryOptions();
    const { loadingRegions, regionOptions } = useRegionOptions();
    const [page, setPage] = useState(1);
    const [settlementType, setSettlementType] = useState("half_month");
    const [cycleKey, setCycleKey] = useState(currentCycleKey);
    const [countryCode, setCountryCode] = useState("");
    const [regionId, setRegionId] = useState("");
    const [selected, setSelected] = useState(() => new Set());
    const [settling, setSettling] = useState(false);

    const filters = useMemo(
        () => ({
            country_code: countryCode,
            cycle_key: cycleKey,
            region_id: regionId,
            role,
            settlement_type: settlementType,
            trigger_mode: "manual",
        }),
        [countryCode, cycleKey, regionId, role, settlementType],
    );
    const query = usePaginatedQuery({
        errorMessage: "获取 Host/Agency 待结算列表失败",
        fetcher: listHostSalarySettlementPending,
        filters,
        page,
        pageSize,
        queryKey: ["host-salary-pending", filters, page],
    });
    const data = query.data || { items: [], page, pageSize, total: 0 };
    const items = data.items || [];
    const total = data.total || 0;
    const allVisibleSelected = items.length > 0 && items.every((item) => selected.has(hostPendingKey(item)));

    useEffect(() => {
        setSelected(new Set());
    }, [filters]);

    const countryFilterOptions = useMemo(() => [["", loadingCountries ? "加载国家中" : "全部国家"], ...countryOptions.map((item) => [item.value, item.label])], [countryOptions, loadingCountries]);
    const regionFilterOptions = useMemo(() => [["", loadingRegions ? "加载区域中" : "全部区域"], ...regionOptions.map((item) => [item.value, item.label])], [loadingRegions, regionOptions]);
    const cycleFilterOptions = useMemo(() => buildCycleOptions(cycleKey, 18), [cycleKey]);

    const changeFilter = (setter) => (value) => {
        setter(value);
        setPage(1);
    };
    const changeRole = (value) => {
        onRoleChange(value);
        setPage(1);
    };
    const resetFilters = () => {
        onRoleChange("bd");
        setSettlementType("half_month");
        setCycleKey(currentCycleKey());
        setCountryCode("");
        setRegionId("");
        setPage(1);
    };
    const toggleOne = (item) => {
        setSelected((current) => {
            const next = new Set(current);
            const key = hostPendingKey(item);
            if (next.has(key)) {
                next.delete(key);
            } else {
                next.add(key);
            }
            return next;
        });
    };
    const toggleVisible = () => {
        setSelected((current) => {
            const next = new Set(current);
            items.forEach((item) => {
                const key = hostPendingKey(item);
                if (allVisibleSelected) {
                    next.delete(key);
                } else {
                    next.add(key);
                }
            });
            return next;
        });
    };
    const settleRows = async (rows) => {
        const userIds = rows
            .map((item) => String(item.userId || "").trim())
            .filter((id) => /^[1-9]\d*$/.test(id));
        if (!userIds.length) {
            return;
        }
        setSettling(true);
        try {
            const result = await settleHostSalary({
                country_code: countryCode || undefined,
                cycle_key: cycleKey,
                role,
                region_id: Number(regionId || 0) || undefined,
                settlement_type: settlementType,
                trigger_mode: "manual",
                user_ids: userIds,
            });
            showToast({
                message: `结算完成：成功 ${result.successCount}，跳过 ${result.skippedCount}，失败 ${result.failureCount}`,
                severity: result.failureCount > 0 ? "warning" : "success",
            });
            setSelected(new Set());
            await query.reload();
        } catch (error) {
            showToast({ message: error?.message || "Host/Agency 工资结算失败", severity: "error" });
        } finally {
            setSettling(false);
        }
    };
    const settleSelected = () => {
        settleRows(items.filter((item) => selected.has(hostPendingKey(item))));
    };
    const tableColumns = [
        {
            key: "select",
            label: (
                <Checkbox
                    checked={allVisibleSelected}
                    disabled={!items.length}
                    indeterminate={selected.size > 0 && !allVisibleSelected}
                    size="small"
                    onChange={toggleVisible}
                />
            ),
            width: "64px",
            resizable: false,
            render: (item) => (
                <Checkbox
                    checked={selected.has(hostPendingKey(item))}
                    size="small"
                    onChange={() => toggleOne(item)}
                />
            ),
        },
        ...hostPendingColumns,
        {
            key: "actions",
            label: "操作",
            width: "minmax(120px, 0.55fr)",
            render: (item) =>
                <Button
                    disabled={!abilities.canSettleSalary || settling}
                    size="small"
                    startIcon={<PlayArrowOutlined fontSize="small" />}
                    variant="secondary"
                    onClick={() => settleRows([item])}
                >
                    结算
                </Button>
        },
    ];
    const hasFilters =
        role !== "bd" || settlementType !== "half_month" || cycleKey !== currentCycleKey() || countryCode || regionId;

    return (
        <>
            <AdminListToolbar
                actions={
                    <Button
                        disabled={!abilities.canSettleSalary || settling || selected.size === 0}
                        startIcon={<PlayArrowOutlined fontSize="small" />}
                        variant="primary"
                        onClick={settleSelected}
                    >
                        批量结算
                    </Button>
                }
                filters={
                    <div className={styles.toolbarFilters}>
                        <AdminFilterSelect label="角色" options={pendingRoleOptions} value={role} onChange={changeRole} />
                        <AdminFilterSelect
                            label="结算类型"
                            options={settlementTypeOptions.filter(([value]) => value !== "")}
                            value={settlementType}
                            onChange={changeFilter(setSettlementType)}
                        />
                        <AdminFilterSelect label="账单周期" options={cycleFilterOptions} value={cycleKey} onChange={changeFilter(setCycleKey)} />
                        <AdminFilterSelect label="国家" options={countryFilterOptions} value={countryCode} onChange={changeFilter(setCountryCode)} />
                        <AdminFilterSelect label="区域" options={regionFilterOptions} value={regionId} onChange={changeFilter(setRegionId)} />
                        <AdminFilterResetButton disabled={!hasFilters} onClick={resetFilters} />
                    </div>
                }
            />
            <DataState error={query.error} loading={query.loading} onRetry={query.reload}>
                <AdminListBody>
                    <DataTable
                        columns={tableColumns}
                        items={items}
                        minWidth="1540px"
                        pagination={paginationProps(data, page, total, setPage)}
                        rowKey={hostPendingKey}
                    />
                </AdminListBody>
            </DataState>
        </>
    );
}

// HostRecordsPanel 保留原 Host/Agency 结算记录查询，避免新增 BD/Admin tab 后丢失主播工资查账入口。
function HostRecordsPanel() {
    const [page, setPage] = useState(1);
    const [cycleKey, setCycleKey] = useState("");
    const [userFilter, setUserFilter] = useState(emptyUserIdentityFilter);
    const [agencyOwnerFilter, setAgencyOwnerFilter] = useState(emptyUserIdentityFilter);
    const [settlementType, setSettlementType] = useState("");
    const [status, setStatus] = useState("");
    const [timeRange, setTimeRange] = useState({ endMs: "", startMs: "" });

    // filters 使用后端 snake_case 字段，直接进入 apiRequest query，减少额外字段映射层。
    const filters = useMemo(
        () => ({
            cycle_key: cycleKey,
            end_at_ms: timeRange.endMs || "",
            settlement_type: settlementType,
            start_at_ms: timeRange.startMs || "",
            status,
            ...userIdentityFilterParams(userFilter),
            ...userIdentityFilterParams(agencyOwnerFilter, {
                displayUserId: "agency_owner_display_user_id",
                userId: "agency_owner_user_id",
                username: "agency_owner_username",
            }),
        }),
        [agencyOwnerFilter, cycleKey, settlementType, status, timeRange.endMs, timeRange.startMs, userFilter],
    );
    const query = usePaginatedQuery({
        errorMessage: "获取工资结算记录失败",
        fetcher: listHostSalarySettlements,
        filters,
        page,
        pageSize,
        queryKey: ["host-salary-settlements", filters, page],
    });
    const data = query.data || { items: [], page, pageSize, total: 0 };
    const items = data.items || [];
    const total = data.total || 0;

    const changeFilter = (setter) => (value) => {
        // 任一筛选变化都回到第一页，避免翻页状态导致新条件下看起来“没有数据”。
        setter(value);
        setPage(1);
    };
    const changeTimeRange = (nextRange) => {
        setTimeRange(nextRange);
        setPage(1);
    };
    const resetFilters = () => {
        setAgencyOwnerFilter(emptyUserIdentityFilter);
        setCycleKey("");
        setSettlementType("");
        setStatus("");
        setTimeRange({ endMs: "", startMs: "" });
        setUserFilter(emptyUserIdentityFilter);
        setPage(1);
    };
    const tableColumns = hostRecordColumns.map((column) => {
        // 列筛选挂在 DataTable 列定义上，保持筛选 UI 与列语义一致。
        if (column.key === "host") {
            return {
                ...column,
                filter: createUserIdentityColumnFilter({
                    value: userFilter,
                    onChange: changeFilter(setUserFilter),
                }),
            };
        }
        if (column.key === "agency") {
            return {
                ...column,
                filter: createUserIdentityColumnFilter({
                    value: agencyOwnerFilter,
                    onChange: changeFilter(setAgencyOwnerFilter),
                }),
            };
        }
        if (column.key === "cycle") {
            return {
                ...column,
                filter: createTextColumnFilter({
                    placeholder: "周期 key",
                    value: cycleKey,
                    onChange: changeFilter(setCycleKey),
                }),
            };
        }
        if (column.key === "status") {
            return {
                ...column,
                filter: createOptionsColumnFilter({
                    options: statusOptions,
                    value: status,
                    onChange: changeFilter(setStatus),
                }),
            };
        }
        return column;
    });
    const hasFilters =
        !isUserIdentityFilterEmpty(agencyOwnerFilter) ||
        cycleKey ||
        settlementType ||
        status ||
        timeRange.startMs ||
        timeRange.endMs ||
        !isUserIdentityFilterEmpty(userFilter);

    return (
        <>
            <AdminListToolbar
                filters={
                    <div className={styles.toolbarFilters}>
                        <TimeRangeFilter value={timeRange} onChange={changeTimeRange} />
                        <AdminFilterSelect
                            label="结算类型"
                            options={settlementTypeOptions}
                            value={settlementType}
                            onChange={changeFilter(setSettlementType)}
                        />
                        <AdminFilterResetButton disabled={!hasFilters} onClick={resetFilters} />
                    </div>
                }
            />
            <DataState error={query.error} loading={query.loading} onRetry={query.reload}>
                <AdminListBody>
                    <DataTable
                        columns={tableColumns}
                        items={items}
                        minWidth="1420px"
                        pagination={paginationProps(data, page, total, setPage)}
                        rowKey={(item) => item.settlementId}
                    />
                </AdminListBody>
            </DataState>
        </>
    );
}

// TeamPendingPanel 是人工结算入口：列表金额来自后端候选计算，批量按钮只提交当前勾选用户。
function TeamPendingPanel({ onRoleChange, role }) {
    const abilities = useHostAgencyPolicyAbilities();
    const { showToast } = useToast();
    const { countryOptions, loadingCountries } = useCountryOptions();
    const { loadingRegions, regionOptions } = useRegionOptions();
    const [page, setPage] = useState(1);
    const [cycleKey, setCycleKey] = useState(defaultCycleKey);
    const [countryCode, setCountryCode] = useState("");
    const [regionId, setRegionId] = useState("");
    const [selected, setSelected] = useState(() => new Set());
    const [settling, setSettling] = useState(false);

    // 待结算只处理人工政策；自动政策没有人工待结算入口，只在记录里查实际落库结果。
    const filters = useMemo(
        () => ({
            country_code: countryCode,
            cycle_key: cycleKey,
            policy_type: role,
            region_id: regionId,
            trigger_mode: "manual",
        }),
        [countryCode, cycleKey, regionId, role],
    );
    const query = usePaginatedQuery({
        errorMessage: "获取 BD/Admin 待结算列表失败",
        fetcher: listTeamSalarySettlementPending,
        filters,
        page,
        pageSize,
        queryKey: ["team-salary-pending", filters, page],
    });
    const data = query.data || { items: [], page, pageSize, total: 0 };
    const items = data.items || [];
    const total = data.total || 0;
    const allVisibleSelected = items.length > 0 && items.every((item) => selected.has(teamPendingKey(item)));

    useEffect(() => {
        // 筛选条件变化后清空勾选，避免把上一批用户带入当前国家或周期的结算请求。
        setSelected(new Set());
    }, [filters]);

    const countryFilterOptions = useMemo(() => [["", loadingCountries ? "加载国家中" : "全部国家"], ...countryOptions.map((item) => [item.value, item.label])], [countryOptions, loadingCountries]);
    const regionFilterOptions = useMemo(() => [["", loadingRegions ? "加载区域中" : "全部区域"], ...regionOptions.map((item) => [item.value, item.label])], [loadingRegions, regionOptions]);
    const cycleFilterOptions = useMemo(() => buildCycleOptions(cycleKey, 18), [cycleKey]);

    const changeFilter = (setter) => (value) => {
        // 国家/区域/周期变化后必须重算候选，不保留旧页码。
        setter(value);
        setPage(1);
    };
    const changeRole = (value) => {
        onRoleChange(value);
        setPage(1);
    };
    const resetFilters = () => {
        onRoleChange("bd");
        setCycleKey(defaultCycleKey());
        setCountryCode("");
        setRegionId("");
        setPage(1);
    };
    const toggleOne = (item) => {
        setSelected((current) => {
            // 选择 key 包含角色、周期、区域和用户，防止同一用户跨区域或跨周期时互相污染。
            const next = new Set(current);
            const key = teamPendingKey(item);
            if (next.has(key)) {
                next.delete(key);
            } else {
                next.add(key);
            }
            return next;
        });
    };
    const toggleVisible = () => {
        setSelected((current) => {
            // 表头复选框只操作当前页，避免用户在未看见的分页数据上误触批量结算。
            const next = new Set(current);
            items.forEach((item) => {
                const key = teamPendingKey(item);
                if (allVisibleSelected) {
                    next.delete(key);
                } else {
                    next.add(key);
                }
            });
            return next;
        });
    };
    const settleSelected = async () => {
        // 只从当前页 items 中提取已勾选用户，服务端仍会再次按 user_ids 白名单过滤。
        const userIds = items
            .filter((item) => selected.has(teamPendingKey(item)))
            .map((item) => String(item.userId || "").trim())
            .filter((id) => /^[1-9]\d*$/.test(id));
        if (!userIds.length) {
            return;
        }
        setSettling(true);
        try {
            // trigger_mode 随页面筛选提交，保证“手动政策”和“自动政策”不会交叉结算。
            const result = await settleTeamSalary({
                country_code: countryCode || undefined,
                cycle_key: cycleKey,
                policy_type: role,
                region_id: Number(regionId || 0) || undefined,
                trigger_mode: "manual",
                user_ids: userIds,
            });
            showToast({
                message: `结算完成：成功 ${result.successCount}，跳过 ${result.skippedCount}，失败 ${result.failureCount}`,
                severity: result.failureCount > 0 ? "warning" : "success",
            });
            setSelected(new Set());
            await query.reload();
        } catch (error) {
            showToast({ message: error?.message || "工资结算失败", severity: "error" });
        } finally {
            setSettling(false);
        }
    };

    const tableColumns = [
        {
            key: "select",
            label: (
                <Checkbox
                    checked={allVisibleSelected}
                    disabled={!items.length}
                    indeterminate={selected.size > 0 && !allVisibleSelected}
                    size="small"
                    onChange={toggleVisible}
                />
            ),
            width: "64px",
            resizable: false,
            render: (item) => (
                <Checkbox checked={selected.has(teamPendingKey(item))} size="small" onChange={() => toggleOne(item)} />
            ),
        },
        ...teamPendingColumns,
    ];
    // 默认值也纳入 hasFilters，这样运营能一键回到“BD + 手动政策 + 上月周期”的标准入口。
    const hasFilters = role !== "bd" || cycleKey !== defaultCycleKey() || countryCode || regionId;

    return (
        <>
            <AdminListToolbar
                actions={
                    <Button
                        disabled={!abilities.canSettleSalary || settling || selected.size === 0}
                        startIcon={<PlayArrowOutlined fontSize="small" />}
                        variant="primary"
                        onClick={settleSelected}
                    >
                        批量结算
                    </Button>
                }
                filters={
                    <div className={styles.toolbarFilters}>
                        <AdminFilterSelect
                            label="角色"
                            options={pendingRoleOptions}
                            value={role}
                            onChange={changeRole}
                        />
                        <AdminFilterSelect label="账单周期" options={cycleFilterOptions} value={cycleKey} onChange={changeFilter(setCycleKey)} />
                        <AdminFilterSelect label="国家" options={countryFilterOptions} value={countryCode} onChange={changeFilter(setCountryCode)} />
                        <AdminFilterSelect label="区域" options={regionFilterOptions} value={regionId} onChange={changeFilter(setRegionId)} />
                        <AdminFilterResetButton disabled={!hasFilters} onClick={resetFilters} />
                    </div>
                }
            />
            <DataState error={query.error} loading={query.loading} onRetry={query.reload}>
                <AdminListBody>
                    <DataTable
                        columns={tableColumns}
                        items={items}
                        minWidth="1280px"
                        pagination={paginationProps(data, page, total, setPage)}
                        rowKey={teamPendingKey}
                    />
                </AdminListBody>
            </DataState>
        </>
    );
}

// TeamRecordsPanel 查询 BD/Admin 结算记录，和待结算页分开，避免查账筛选影响待结算批量操作。
function TeamRecordsPanel() {
    const [page, setPage] = useState(1);
    const [policyType, setPolicyType] = useState("");
    const [triggerMode, setTriggerMode] = useState("");
    const [cycleKey, setCycleKey] = useState("");
    const [countryCode, setCountryCode] = useState("");
    const [userFilter, setUserFilter] = useState(emptyUserIdentityFilter);
    const [status, setStatus] = useState("");
    const [timeRange, setTimeRange] = useState({ endMs: "", startMs: "" });

    // 记录查询支持国家代码筛选；后端会转换为 region_id 集合过滤结算记录。
    const filters = useMemo(
        () => ({
            country_code: countryCode,
            cycle_key: cycleKey,
            end_at_ms: timeRange.endMs || "",
            policy_type: policyType,
            start_at_ms: timeRange.startMs || "",
            status,
            trigger_mode: triggerMode,
            ...userIdentityFilterParams(userFilter),
        }),
        [countryCode, cycleKey, policyType, status, timeRange.endMs, timeRange.startMs, triggerMode, userFilter],
    );
    const query = usePaginatedQuery({
        errorMessage: "获取 BD/Admin 结算记录失败",
        fetcher: listTeamSalarySettlementRecords,
        filters,
        page,
        pageSize,
        queryKey: ["team-salary-records", filters, page],
    });
    const data = query.data || { items: [], page, pageSize, total: 0 };
    const items = data.items || [];
    const total = data.total || 0;

    const changeFilter = (setter) => (value) => {
        // 记录页所有筛选统一重置到第一页，和其它后台列表交互保持一致。
        setter(value);
        setPage(1);
    };
    const resetFilters = () => {
        setPolicyType("");
        setTriggerMode("");
        setCycleKey("");
        setCountryCode("");
        setStatus("");
        setTimeRange({ endMs: "", startMs: "" });
        setUserFilter(emptyUserIdentityFilter);
        setPage(1);
    };
    const tableColumns = teamRecordColumns.map((column) => {
        // 用户、周期、状态保留列内筛选；角色/触发方式/国家放顶部，便于组合查询。
        if (column.key === "user") {
            return {
                ...column,
                filter: createUserIdentityColumnFilter({
                    value: userFilter,
                    onChange: changeFilter(setUserFilter),
                }),
            };
        }
        if (column.key === "cycle") {
            return {
                ...column,
                filter: createTextColumnFilter({
                    placeholder: "周期 key",
                    value: cycleKey,
                    onChange: changeFilter(setCycleKey),
                }),
            };
        }
        if (column.key === "status") {
            return {
                ...column,
                filter: createOptionsColumnFilter({
                    options: statusOptions,
                    value: status,
                    onChange: changeFilter(setStatus),
                }),
            };
        }
        return column;
    });
    const hasFilters =
        policyType ||
        triggerMode ||
        cycleKey ||
        countryCode ||
        status ||
        timeRange.startMs ||
        timeRange.endMs ||
        !isUserIdentityFilterEmpty(userFilter);

    return (
        <>
            <AdminListToolbar
                filters={
                    <div className={styles.toolbarFilters}>
                        <TimeRangeFilter
                            value={timeRange}
                            onChange={(value) => {
                                setTimeRange(value);
                                setPage(1);
                            }}
                        />
                        <AdminFilterSelect
                            label="角色"
                            options={policyTypeAllOptions}
                            value={policyType}
                            onChange={changeFilter(setPolicyType)}
                        />
                        <AdminFilterSelect
                            label="触发"
                            options={triggerAllOptions}
                            value={triggerMode}
                            onChange={changeFilter(setTriggerMode)}
                        />
                        <InlineFilter
                            label="国家"
                            placeholder="国家代码"
                            value={countryCode}
                            onChange={changeFilter(setCountryCode)}
                        />
                        <AdminFilterResetButton disabled={!hasFilters} onClick={resetFilters} />
                    </div>
                }
            />
            <DataState error={query.error} loading={query.loading} onRetry={query.reload}>
                <AdminListBody>
                    <DataTable
                        columns={tableColumns}
                        items={items}
                        minWidth="1280px"
                        pagination={paginationProps(data, page, total, setPage)}
                        rowKey={(item) => item.settlementId}
                    />
                </AdminListBody>
            </DataState>
        </>
    );
}

// hostRecordColumns 展示 Host/Agency 的原始结算事实，包括主播工资、金币奖励、代理工资和剩余折美元。
const hostRecordColumns = [
    {
        key: "host",
        label: "主播",
        width: "minmax(240px, 1.1fr)",
        render: (item) => <UserCell fallbackId={item.userId} user={item.user} />,
    },
    {
        key: "agency",
        label: "代理",
        width: "minmax(220px, 1fr)",
        render: (item) => <UserCell fallbackId={item.agencyOwnerUserId} user={item.agencyOwner} />,
    },
    {
        key: "cycle",
        label: "周期",
        width: "minmax(170px, 0.8fr)",
        render: (item) => <CycleCell item={item} />,
    },
    {
        key: "level",
        label: "等级/钻石",
        width: "minmax(150px, 0.7fr)",
        render: (item) => <HostLevelCell item={item} />,
    },
    {
        key: "hostReward",
        label: "主播奖励",
        width: "minmax(170px, 0.8fr)",
        render: (item) => <HostRewardCell item={item} />,
    },
    {
        key: "agencyReward",
        label: "代理/剩余",
        width: "minmax(170px, 0.8fr)",
        render: (item) => <AgencyRewardCell item={item} />,
    },
    {
        key: "status",
        label: "状态",
        width: "minmax(120px, 0.55fr)",
        render: (item) => <StatusCell item={item} />,
    },
    {
        key: "createdAtMs",
        label: "时间",
        width: "minmax(170px, 0.8fr)",
        render: (item) => formatMillis(item.createdAtMs),
    },
];

// hostPendingColumns 展示 Host/Agency 当前账单差额；结算按钮单独放在操作列，便于自动政策行只读展示。
const hostPendingColumns = [
    {
        key: "host",
        label: "主播",
        width: "minmax(240px, 1.1fr)",
        render: (item) => <UserCell fallbackId={item.userId} user={item.user} />,
    },
    {
        key: "agency",
        label: "代理",
        width: "minmax(220px, 1fr)",
        render: (item) => <UserCell fallbackId={item.agencyOwnerUserId} user={item.agencyOwner} />,
    },
    {
        key: "scope",
        label: "周期/政策",
        width: "minmax(230px, 1fr)",
        render: (item) => (
            <div className={styles.stack}>
                <span>
                    {item.cycleKey || "-"} · {settlementTypeLabel(item.settlementType)}
                </span>
                <span className={styles.meta}>{item.regionName || `区域 ${item.regionId || "-"}`}</span>
                <span className={styles.meta}>{item.policyName || `政策 ${item.policyId || "-"}`}</span>
            </div>
        ),
    },
    {
        key: "level",
        label: "等级/钻石",
        width: "minmax(160px, 0.75fr)",
        render: (item) => (
            <div className={styles.stack}>
                <span>{item.levelNo > 0 ? `等级 ${item.levelNo}` : "未达等级"}</span>
                <span className={styles.meta}>{formatNumber(item.totalDiamonds)} 钻石</span>
                <span className={styles.meta}>门槛 {formatNumber(item.requiredDiamonds)}</span>
            </div>
        ),
    },
    {
        key: "hostReward",
        label: "主播待发",
        width: "minmax(170px, 0.8fr)",
        render: (item) => (
            <div className={styles.stack}>
                <span className={styles.amountPositive}>{formatMoneyDelta(item.hostSalaryUsdDelta)}</span>
                <span className={styles.meta}>金币 {formatSignedInteger(item.hostCoinRewardDelta)}</span>
            </div>
        ),
    },
    {
        key: "agencyReward",
        label: "代理/剩余",
        width: "minmax(170px, 0.8fr)",
        render: (item) => <AgencyRewardCell item={item} />,
    },
    {
        key: "total",
        label: "待发总额",
        width: "minmax(150px, 0.7fr)",
        render: (item) => <span className={styles.amountPositive}>{formatMoneyDelta(item.totalUsdDelta)}</span>,
    },
    {
        key: "progress",
        label: "已结进度",
        width: "minmax(170px, 0.8fr)",
        render: (item) => (
            <div className={styles.stack}>
                <span>等级 {item.settledLevelNo || 0}</span>
                <span className={styles.meta}>主播 ${item.settledHostSalaryUsd || "0"}</span>
                <span className={styles.meta}>代理 ${item.settledAgencySalaryUsd || "0"}</span>
            </div>
        ),
    },
    {
        key: "status",
        label: "状态",
        width: "minmax(120px, 0.55fr)",
        render: (item) => <StatusCell item={item} />,
    },
];

// teamPendingColumns 展示 BD/Admin 的“现在会发多少钱”和“此前已发到哪一档”。
const teamPendingColumns = [
    {
        key: "user",
        label: "用户",
        width: "minmax(230px, 1fr)",
        render: (item) => <UserCell fallbackId={item.userId} user={item.user} />,
    },
    {
        key: "scope",
        label: "周期/区域",
        width: "minmax(180px, 0.8fr)",
        render: (item) => (
            <div className={styles.stack}>
                <span>
                    {roleLabel(item.policyType)} · {item.cycleKey || "-"}
                </span>
                <span className={styles.meta}>{item.regionName || `区域 ${item.regionId || "-"}`}</span>
            </div>
        ),
    },
    {
        key: "income",
        label: "收入基数",
        width: "minmax(150px, 0.7fr)",
        render: (item) => <MoneyStack primary={item.incomeUsd} secondary="累计收入" />,
    },
    {
        key: "level",
        label: "政策/档位",
        width: "minmax(210px, 0.9fr)",
        render: (item) => (
            <div className={styles.stack}>
                <span>{item.levelNo > 0 ? `等级 ${item.levelNo}` : "未达等级"}</span>
                <span className={styles.meta}>{item.policyName || `政策 ${item.policyId || "-"}`}</span>
            </div>
        ),
    },
    {
        key: "salary",
        label: "待发工资",
        width: "minmax(170px, 0.8fr)",
        render: (item) => (
            <div className={styles.stack}>
                <span className={styles.amountPositive}>{formatMoneyDelta(item.salaryUsdDelta)}</span>
                <span className={styles.meta}>累计目标 ${item.salaryUsdTarget || "0"}</span>
            </div>
        ),
    },
    {
        key: "progress",
        label: "已结进度",
        width: "minmax(180px, 0.8fr)",
        render: (item) => (
            <div className={styles.stack}>
                <span>${item.settledSalaryUsd || "0"}</span>
                <span className={styles.meta}>已结等级 {item.settledLevelNo || 0}</span>
            </div>
        ),
    },
];

// teamRecordColumns 展示已落库的 BD/Admin 结算记录；settlementId 通过 rowKey 保持唯一。
const teamRecordColumns = [
    {
        key: "user",
        label: "用户",
        width: "minmax(230px, 1fr)",
        render: (item) => <UserCell fallbackId={item.userId} user={item.user} />,
    },
    {
        key: "cycle",
        label: "周期/角色",
        width: "minmax(170px, 0.8fr)",
        render: (item) => (
            <div className={styles.stack}>
                <span>{item.cycleKey || "-"}</span>
                <span className={styles.meta}>
                    {roleLabel(item.policyType)} · {triggerLabel(item.triggerMode)}
                </span>
            </div>
        ),
    },
    {
        key: "income",
        label: "收入基数",
        width: "minmax(150px, 0.7fr)",
        render: (item) => <MoneyStack primary={item.incomeUsd} secondary={`等级 ${item.levelNo || 0}`} />,
    },
    {
        key: "salary",
        label: "发放工资",
        width: "minmax(160px, 0.75fr)",
        render: (item) => <span className={styles.amountPositive}>{formatMoneyDelta(item.salaryUsdDelta)}</span>,
    },
    {
        key: "policy",
        label: "政策",
        width: "minmax(130px, 0.55fr)",
        render: (item) => `政策 ${item.policyId || "-"}`,
    },
    {
        key: "status",
        label: "状态",
        width: "minmax(120px, 0.55fr)",
        render: (item) => <StatusCell item={item} />,
    },
    {
        key: "createdAtMs",
        label: "时间",
        width: "minmax(170px, 0.8fr)",
        render: (item) => formatMillis(item.createdAtMs),
    },
];

// InlineFilter 是本页面的轻量文本筛选控件，用于周期、国家代码、区域 ID 这类短字段。
function InlineFilter({ label, onChange, placeholder, value }) {
    return (
        <label className={styles.inlineFilter}>
            <span>{label}</span>
            <input placeholder={placeholder} value={value} onChange={(event) => onChange(event.target.value)} />
        </label>
    );
}

// UserCell 统一展示用户资料；没有资料时仍显示 user_id，确保查账可定位。
function UserCell({ fallbackId, user }) {
    const idText = userIdText(user, fallbackId);
    if (!idText) {
        return "-";
    }
    return <AdminUserIdentity openInAppUserDetail user={{ ...(user || {}), userId: user?.userId || fallbackId }} />;
}

// CycleCell 展示 Host/Agency 周期和结算类型。
function CycleCell({ item }) {
    return (
        <div className={styles.stack}>
            <span>{item.cycleKey || "-"}</span>
            <span className={styles.meta}>
                {settlementTypeLabel(item.settlementType)} · {triggerLabel(item.triggerMode)} ·{" "}
                {roleLabel(item.settlementRole)}
            </span>
        </div>
    );
}

// HostLevelCell 展示主播档位和钻石累计，方便对照 Host 政策表。
function HostLevelCell({ item }) {
    return (
        <div className={styles.stack}>
            <span>{item.levelNo > 0 ? `等级 ${item.levelNo}` : "未达等级"}</span>
            <span className={styles.meta}>{formatNumber(item.totalDiamonds)} 钻石</span>
            <span className={styles.meta}>政策 {item.policyId || "-"}</span>
        </div>
    );
}

// HostRewardCell 展示主播侧本次增量奖励。
function HostRewardCell({ item }) {
    return (
        <div className={styles.stack}>
            <span className={styles.amountPositive}>{formatMoneyDelta(item.hostSalaryUsdDelta)}</span>
            <span className={styles.meta}>金币 {formatSignedInteger(item.hostCoinRewardDelta)}</span>
        </div>
    );
}

// AgencyRewardCell 展示代理工资和月底剩余钻石折美元。
function AgencyRewardCell({ item }) {
    return (
        <div className={styles.stack}>
            <span className={styles.amountPositive}>{formatMoneyDelta(item.agencySalaryUsdDelta)}</span>
            <span className={styles.meta}>剩余折美元 {formatMoneyDelta(item.residualUsdDelta)}</span>
        </div>
    );
}

// MoneyStack 固定两行金额展示，避免表格列因文案变化跳动。
function MoneyStack({ primary, secondary }) {
    return (
        <div className={styles.stack}>
            <span>${primary || "0"}</span>
            <span className={styles.meta}>{secondary}</span>
        </div>
    );
}

// StatusCell 统一状态徽标，失败或跳过原因放在第二行。
function StatusCell({ item }) {
    return (
        <div className={styles.stack}>
            <span className={`status-badge status-badge--${statusTone(item.status)}`}>{statusLabel(item.status)}</span>
            {item.reason ? <span className={styles.meta}>{item.reason}</span> : null}
        </div>
    );
}

// paginationProps 只在 total > 0 时渲染分页，空表保持更干净的空状态。
function paginationProps(data, page, total, onPageChange) {
    return total > 0
        ? {
              page,
              pageSize: data.pageSize || pageSize,
              total,
              onPageChange,
          }
        : undefined;
}

// teamPendingKey 绑定角色、周期、区域和用户，保证多维候选在前端选择集合里唯一。
function teamPendingKey(item) {
    return `${item.policyType}:${item.cycleKey}:${item.regionId}:${item.userId}`;
}

function hostPendingKey(item) {
    return `${item.role}:${item.settlementType}:${item.cycleKey}:${item.regionId}:${item.userId}`;
}

// userIdText 展示短 ID / 长 ID；筛选仍然用长 user_id。
function userIdText(user, fallbackId) {
    const id = String(user?.userId || fallbackId || "").trim();
    if (!id || id === "0") {
        return "";
    }
    const display = String(user?.displayUserId || "").trim();
    return display ? `${display} / ${id}` : id;
}

// defaultCycleKey 计算上一个 UTC 自然月，和后端 previousMonthCycleKey 保持同一周期口径。
function defaultCycleKey() {
    const now = new Date();
    const firstOfMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
    firstOfMonth.setUTCMonth(firstOfMonth.getUTCMonth() - 1);
    return `${firstOfMonth.getUTCFullYear()}-${String(firstOfMonth.getUTCMonth() + 1).padStart(2, "0")}`;
}

// currentCycleKey 计算当前 UTC 自然月，和 Host/Agency 周期账户的 yyyy-MM 保持一致。
function currentCycleKey() {
    const now = new Date();
    return `${now.getUTCFullYear()}-${String(now.getUTCMonth() + 1).padStart(2, "0")}`;
}

function buildCycleOptions(selectedCycleKey, monthCount) {
    const now = new Date();
    const anchor = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
    const options = [];
    for (let index = 0; index < monthCount; index += 1) {
        const item = new Date(anchor);
        item.setUTCMonth(anchor.getUTCMonth() - index);
        const value = `${item.getUTCFullYear()}-${String(item.getUTCMonth() + 1).padStart(2, "0")}`;
        options.push([value, value]);
    }
    if (selectedCycleKey && !options.some(([value]) => value === selectedCycleKey)) {
        return [[selectedCycleKey, selectedCycleKey], ...options];
    }
    return options;
}

// settlementTypeLabel 把 Host/Agency 结算类型枚举转成运营文案。
function settlementTypeLabel(value) {
    return (
        {
            daily: "日结",
            half_month: "半月结算",
            month_end: "月底清算",
        }[value] ||
        value ||
        "-"
    );
}

// statusLabel 把通用结算状态枚举转成运营文案。
function statusLabel(value) {
    return (
        {
            failed: "失败",
            pending: "待结算",
            skipped: "跳过",
            succeeded: "成功",
        }[value] ||
        value ||
        "-"
    );
}

// statusTone 把业务状态映射为现有 status-badge 视觉语义。
function statusTone(value) {
    return (
        {
            failed: "danger",
            pending: "warning",
            skipped: "warning",
            succeeded: "running",
        }[value] || "stopped"
    );
}

// roleLabel 把 policy_type 展示为工资角色名称。
function roleLabel(value) {
    return (
        {
            admin: "Admin",
            agency: "Agency",
            all: "Host/Agency",
            bd: "BD",
            host: "Host",
        }[value] ||
        value ||
        "-"
    );
}

// triggerLabel 把触发方式展示为自动/手动。
function triggerLabel(value) {
    return value === "automatic" ? "自动" : value === "manual" ? "手动" : value || "-";
}

// formatMoneyDelta 专门展示“本次增量”，正数带 +，0 保持中性。
function formatMoneyDelta(value) {
    const number = Number(value || 0);
    if (!Number.isFinite(number) || number === 0) {
        return "$0.00";
    }
    const prefix = number > 0 ? "+$" : "-$";
    return `${prefix}${Math.abs(number).toFixed(2)}`;
}

// formatSignedInteger 展示金币增量，正数带 +。
function formatSignedInteger(value) {
    const number = Number(value || 0);
    if (!Number.isFinite(number) || number === 0) {
        return "0";
    }
    return `${number > 0 ? "+" : ""}${formatNumber(number)}`;
}

// formatNumber 统一数字千分位，表格内不做本地状态计算。
function formatNumber(value) {
    return new Intl.NumberFormat("zh-CN").format(Number(value || 0));
}
