import { useCallback, useEffect, useMemo, useState } from "react";
import { getWheelConfig, getWheelDrawSummary, listWheelDraws, updateWheelConfig } from "@/features/operations/api";
import { listResourceGroups } from "@/features/resources/api";
import { wheelConfigFormSchema } from "@/features/operations/schema";
import { useAdminQuery } from "@/shared/hooks/useAdminQuery.js";
import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import { applyProbabilityMap, correctRTPProbabilities, decimal } from "@/shared/utils/rtpProbability.js";

const pageSize = 50;
const probabilityAffectingFields = new Set([
    "drawPriceCoins",
    "targetRTPPercent",
    "rewardType",
    "rewardCoins",
    "rtpValueCoins",
]);
export const wheelPools = [
    { key: "classic", label: "Classic", tierCount: 8 },
    { key: "luxury", label: "Luxury", tierCount: 8 },
    { key: "advanced", label: "Advanced", tierCount: 12 },
];

const defaultForm = defaultFormFor("classic");

function defaultFormFor(wheelId) {
    const pool = wheelPools.find((item) => item.key === wheelId) || wheelPools[0];
    return {
        drawPriceCoins: 10000,
        effectiveFromMs: 0,
        enabled: true,
        initialPoolCoins: 0,
        maxSingleRTPPayout: 0,
        poolRatePercent: 90,
        poolReserveCoins: 0,
        settlementWindowDraws: 1000,
        targetRTPPercent: 90,
        tiers: [],
        wheelId: pool.key,
    };
}

export function useWheelPage() {
    const { showToast } = useToast();
    const [wheelId, setWheelId] = useState("classic");
    const [userId, setUserId] = useState("");
    const [status, setStatus] = useState("");
    const [page, setPage] = useState(1);
    const [form, setForm] = useState(defaultForm);
    const [saving, setSaving] = useState(false);

    const configQueryFn = useCallback(() => getWheelConfig(wheelId), [wheelId]);
    const configQuery = useAdminQuery(configQueryFn, {
        errorMessage: "获取转盘配置失败",
        queryKey: ["wheel-config", wheelId],
    });

    const summaryFilters = useMemo(
        () => ({
            status,
            user_id: userId,
            wheel_id: wheelId,
        }),
        [status, userId, wheelId],
    );
    const summaryQueryFn = useCallback(() => getWheelDrawSummary(summaryFilters), [summaryFilters]);
    const summaryQuery = useAdminQuery(summaryQueryFn, {
        errorMessage: "获取转盘汇总失败",
        initialData: null,
        queryKey: ["wheel-draw-summary", summaryFilters],
    });

    const drawQuery = usePaginatedQuery({
        errorMessage: "获取转盘抽奖记录失败",
        fetcher: listWheelDraws,
        filters: summaryFilters,
        page,
        pageSize,
        queryKey: ["wheel-draws", summaryFilters, page],
    });

    const resourceGroupQueryFn = useCallback(
        () => listResourceGroups({ page: 1, page_size: 300, status: "active" }),
        [],
    );
    const resourceGroupQuery = useAdminQuery(resourceGroupQueryFn, {
        errorMessage: "获取资源组失败",
        initialData: { items: [] },
        queryKey: ["wheel-resource-groups"],
    });

    useEffect(() => {
        if (configQuery.data) {
            setForm(configToForm(configQuery.data));
            return;
        }
        setForm(defaultFormFor(wheelId));
    }, [configQuery.data, wheelId]);

    const filtersDirty = Boolean(userId || status || wheelId !== "classic");

    const changeWheelId = (value) => {
        setWheelId(value.trim() || "classic");
        setPage(1);
    };

    const selectPool = (value) => {
        const nextWheelId = wheelPools.some((pool) => pool.key === value) ? value : "classic";
        setWheelId(nextWheelId);
        setPage(1);
    };

    const changeUserId = (value) => {
        setUserId(value);
        setPage(1);
    };

    const changeStatus = (value) => {
        setStatus(value);
        setPage(1);
    };

    const resetFilters = () => {
        setWheelId("classic");
        setUserId("");
        setStatus("");
        setPage(1);
    };

    const changeFormField = (field, value) => {
        setForm((current) => {
            const next = { ...current, [field]: value };
            return probabilityAffectingFields.has(field) ? withGeneratedTierProbabilities(next) : next;
        });
    };

    const changeTierField = (index, field, value) => {
        setForm((current) => {
            const tiers = current.tiers.map((tier, tierIndex) => {
                if (tierIndex !== index) {
                    return tier;
                }
                const next = { ...tier, [field]: value };
                // 道具和装扮只影响展示/背包发放，不进入 RTP 统计；前端在切换类型时立即清零，
                // 这样运营保存前看到的数值和后端实际入库规则一致。
                if (field === "rewardType" && (value === "prop" || value === "dress")) {
                    next.rtpValueCoins = 0;
                    next.rewardCoins = 0;
                    next.tierId = `${current.wheelId}-${tierIndex + 1}`;
                }
                if (field === "rewardType" && value === "coin") {
                    next.rewardId = "";
                    next.rtpValueCoins = Number(next.rewardCoins || 0);
                    next.tierId = `${current.wheelId}-${tierIndex + 1}`;
                }
                if (field === "rewardType" && value === "gift") {
                    next.rewardCoins = 0;
                    next.tierId = `${current.wheelId}-${tierIndex + 1}`;
                }
                if (field === "rewardCoins" && tier.rewardType === "coin") {
                    next.rtpValueCoins = value;
                }
                return next;
            });
            const next = { ...current, tiers };
            return probabilityAffectingFields.has(field) ? withGeneratedTierProbabilities(next) : next;
        });
    };

    const importResourceGroup = (group) => {
        const items = group?.items || [];
        const expectedCount = expectedTierCount(wheelId);
        if (items.length !== expectedCount) {
            showToast(`${poolLabel(wheelId)} 需要 ${expectedCount} 个奖品，当前资源组有 ${items.length} 个`, "error");
            return;
        }
        setForm((current) =>
            withGeneratedTierProbabilities({
                ...current,
                tiers: items.map((item, index) => groupItemToTier(item, wheelId, index)),
            }),
        );
        showToast("资源组已导入，可拖动排序", "success");
    };

    const moveTier = (fromIndex, toIndex) => {
        setForm((current) => {
            if (
                fromIndex === toIndex ||
                fromIndex < 0 ||
                toIndex < 0 ||
                fromIndex >= current.tiers.length ||
                toIndex >= current.tiers.length
            ) {
                return current;
            }
            const tiers = [...current.tiers];
            const [item] = tiers.splice(fromIndex, 1);
            tiers.splice(toIndex, 0, item);
            return withGeneratedTierProbabilities({
                ...current,
                tiers: tiers.map((tier, index) => ({ ...tier, tierId: `${current.wheelId}-${index + 1}` })),
            });
        });
    };

    const submit = async () => {
        const generatedForm = withGeneratedTierProbabilities(form);
        setForm(generatedForm);
        const parsed = wheelConfigFormSchema.safeParse(generatedForm);
        if (!parsed.success) {
            showToast(parsed.error.issues[0]?.message || "转盘配置参数不正确", "error");
            return;
        }

        setSaving(true);
        try {
            await updateWheelConfig(formToPayload(parsed.data));
            showToast("转盘配置已保存", "success");
            setWheelId(parsed.data.wheelId);
            await Promise.all([configQuery.reload(), summaryQuery.reload(), drawQuery.reload()]);
        } catch (err) {
            showToast(err.message || "保存转盘配置失败", "error");
        } finally {
            setSaving(false);
        }
    };

    return {
        changeFormField,
        changeStatus,
        changeTierField,
        changeUserId,
        changeWheelId,
        configQuery,
        drawQuery,
        drawError: drawQuery.error,
        draws: drawQuery.data,
        expectedTierCount: expectedTierCount(wheelId),
        filtersDirty,
        form,
        importResourceGroup,
        moveTier,
        page,
        pageSize,
        resetFilters,
        resourceGroups: resourceGroupQuery.data?.items || [],
        resourceGroupQuery,
        saving,
        selectPool,
        setPage,
        status,
        submit,
        summary: summaryQuery.data,
        summaryQuery,
        userId,
        wheelPools,
        wheelId,
        configError: configQuery.error,
    };
}

function configToForm(config) {
    const wheelId = config.wheelId || "classic";
    const rawTiers = config.tiers || [];
    const tiers = isGeneratedPlaceholderTiers(rawTiers, wheelId) ? [] : normalizeTiers(rawTiers, wheelId);
    return {
        drawPriceCoins: config.drawPriceCoins || defaultForm.drawPriceCoins,
        effectiveFromMs: config.effectiveFromMs || 0,
        enabled: Boolean(config.enabled),
        initialPoolCoins: config.initialPoolCoins || 0,
        maxSingleRTPPayout: config.maxSingleRTPPayout || 0,
        poolRatePercent: config.poolRatePercent || defaultForm.poolRatePercent,
        poolReserveCoins: config.poolReserveCoins || 0,
        settlementWindowDraws: config.settlementWindowDraws || defaultForm.settlementWindowDraws,
        targetRTPPercent: config.targetRTPPercent ?? defaultForm.targetRTPPercent,
        tiers: generateWheelTierProbabilities({
            drawPriceCoins: config.drawPriceCoins || defaultForm.drawPriceCoins,
            targetRTPPercent: config.targetRTPPercent ?? defaultForm.targetRTPPercent,
            tiers,
        }),
        wheelId,
    };
}

function normalizeTiers(tiers, wheelId) {
    return (tiers || []).map((tier, index) => ({
        displayName: tier.displayName || "",
        enabled: true,
        metadataJson: tier.metadataJson || "{}",
        probabilityPercent: tier.probabilityPercent || 0,
        rewardCoins: tier.rewardCoins || 0,
        rewardCount: tier.rewardCount || 0,
        rewardId: tier.rewardId || "",
        rewardType: tier.rewardType || "coin",
        rtpValueCoins: tier.rewardType === "prop" || tier.rewardType === "dress" ? 0 : tier.rtpValueCoins || 0,
        tierId: tier.tierId || `${wheelId}-${index + 1}`,
    }));
}

function isGeneratedPlaceholderTiers(tiers, wheelId) {
    const expectedCount = expectedTierCount(wheelId);
    if (!Array.isArray(tiers) || tiers.length !== expectedCount) {
        return false;
    }
    return tiers.every((tier, index) => {
        const expectedName = `奖品 ${index + 1}`;
        const expectedTierId = `${wheelId}-${index + 1}`;
        return (
            tier.displayName === expectedName &&
            tier.tierId === expectedTierId &&
            tier.rewardType === "coin" &&
            !tier.rewardId &&
            Number(tier.rewardCoins || 0) === 1 &&
            Number(tier.rtpValueCoins || 0) === 1 &&
            Number(tier.rewardCount || 0) === 1
        );
    });
}

function formToPayload(form) {
    return {
        draw_price_coins: Number(form.drawPriceCoins),
        effective_from_ms: Number(form.effectiveFromMs || 0),
        enabled: Boolean(form.enabled),
        initial_pool_coins: Number(form.initialPoolCoins || 0),
        max_single_rtp_payout: Number(form.maxSingleRTPPayout || 0),
        pool_rate_percent: Number(form.poolRatePercent),
        pool_reserve_coins: Number(form.poolReserveCoins || 0),
        settlement_window_draws: Number(form.settlementWindowDraws),
        target_rtp_percent: Number(form.targetRTPPercent),
        tiers: form.tiers.map((tier) => {
            const rewardType = tier.rewardType;
            return {
                display_name: tier.displayName.trim(),
                enabled: true,
                metadata_json: tier.metadataJson.trim() || "{}",
                probability_percent: Number(tier.probabilityPercent),
                reward_coins: Number(rewardType === "coin" ? tier.rewardCoins : 0),
                reward_count: Number(tier.rewardCount || 0),
                reward_id: tier.rewardId.trim(),
                reward_type: rewardType,
                rtp_value_coins: rewardType === "prop" || rewardType === "dress" ? 0 : Number(tier.rtpValueCoins || 0),
                tier_id: tier.tierId.trim(),
            };
        }),
        wheel_id: form.wheelId.trim(),
    };
}

function expectedTierCount(wheelId) {
    return (wheelPools.find((pool) => pool.key === wheelId) || wheelPools[0]).tierCount;
}

function poolLabel(wheelId) {
    return (wheelPools.find((pool) => pool.key === wheelId) || wheelPools[0]).label;
}

export function groupItemToTier(item, wheelId, index) {
    const resource = item.resource || {};
    const isCoin = item.itemType === "wallet_asset" && item.walletAssetType === "COIN";
    const rewardType = isCoin ? "coin" : resourceTypeToRewardType(resource.resourceType);
    const coinValue = isCoin ? Number(item.walletAssetAmount || 0) : Number(resource.coinPrice || 0);
    const metadata = {
        animation_url: isCoin ? "" : resource.animationUrl || "",
        asset_url: resource.assetUrl || "",
        coinPrice: coinValue,
        coin_price: coinValue,
        displayValue: coinValue,
        display_value: coinValue,
        preview_url: resource.previewUrl || resource.assetUrl || "",
        resource_code: resource.resourceCode || "",
        resource_id: resource.resourceId || 0,
        resource_type: resource.resourceType || "",
        value: coinValue,
    };
    return {
        displayName: isCoin
            ? "金币"
            : resource.name || resource.resourceCode || `资源 ${resource.resourceId || index + 1}`,
        enabled: true,
        metadataJson: JSON.stringify(metadata),
        probabilityPercent: 0,
        rewardCoins: isCoin ? coinValue : 0,
        rewardCount: Number(item.quantity || 1),
        rewardId: isCoin ? "" : String(resource.resourceId || item.resourceId || ""),
        rewardType,
        rtpValueCoins: rewardType === "prop" || rewardType === "dress" ? 0 : coinValue,
        tierId: `${wheelId}-${index + 1}`,
    };
}

function withGeneratedTierProbabilities(form) {
    return { ...form, tiers: generateWheelTierProbabilities(form) };
}

export function generateWheelTierProbabilities(form) {
    const tiers = form.tiers || [];
    if (!tiers.length) {
        return tiers;
    }
    // 转盘没有幸运礼物的倍率字段，这里把每个奖档的 RTP 价值换算成“相对单抽价格的倍率”。
    // 道具/装扮不计入 RTP，因此只拿公共公式保留的最小正概率；全无 RTP 奖档时退化为均分，保证仍可发布配置。
    const probabilityByIndex = correctRTPProbabilities(tiers, form.targetRTPPercent, {
        baselineProbability: (tier, index, context) =>
            wheelTierBaselineProbability(tier, index, context, form.drawPriceCoins),
        fallback: "equal",
        multiplier: (tier) => wheelTierMultiplier(tier, form.drawPriceCoins),
        participatesInRTP: wheelTierParticipatesInRTP,
    });
    return applyProbabilityMap(tiers, probabilityByIndex, (value) => Number(value.toFixed(4)));
}

function wheelTierMultiplier(tier, drawPriceCoins) {
    const drawPrice = decimal(drawPriceCoins);
    if (drawPrice <= 0) {
        return 0;
    }
    return wheelTierRTPValueCoins(tier) / drawPrice;
}

function wheelTierBaselineProbability(tier, index, context, drawPriceCoins) {
    if (!wheelTierParticipatesInRTP(tier)) {
        return 0;
    }
    const multiplier = wheelTierMultiplier(tier, drawPriceCoins);
    if (multiplier <= 0) {
        return 0;
    }
    const maxMultiplier = Math.max(multiplier, ...(context.positiveTiers || []).map((item) => item.multiplier));
    return 0.0001 * (maxMultiplier / multiplier);
}

function wheelTierRTPValueCoins(tier) {
    if (tier.rewardType === "coin") {
        return decimal(tier.rewardCoins || tier.rtpValueCoins);
    }
    if (tier.rewardType === "gift") {
        return decimal(tier.rtpValueCoins);
    }
    return 0;
}

function wheelTierParticipatesInRTP(tier) {
    return tier.rewardType === "coin" || tier.rewardType === "gift";
}

function resourceTypeToRewardType(resourceType) {
    const value = String(resourceType || "").toLowerCase();
    if (value === "gift" || value.includes("gift")) {
        return "gift";
    }
    if (value.includes("dress") || value.includes("frame") || value.includes("card") || value.includes("entrance")) {
        return "dress";
    }
    return "prop";
}
