import { useCallback, useEffect, useMemo, useState } from "react";
import {
    getRedPacket,
    getRedPacketConfig,
    listRedPackets,
    retryRedPacketRefund,
    updateRedPacketConfig,
} from "@/features/red-packets/api";
import { useRedPacketAbilities } from "@/features/red-packets/permissions.js";
import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js";
import { useToast } from "@/shared/ui/ToastProvider.jsx";

const pageSize = 50;
const emptyPackets = { items: [], page: 1, pageSize, total: 0 };

const emptyForm = {
    enabled: false,
    countTiers: [""],
    amountTiers: [""],
    delayedOpenSeconds: "0",
    expireSeconds: "86400",
    dailySendLimit: "5",
    ruleUrl: "",
};

export function useRedPacketPage() {
    const abilities = useRedPacketAbilities();
    const { showToast } = useToast();
    const [config, setConfig] = useState(null);
    const [configDrawerOpen, setConfigDrawerOpen] = useState(false);
    const [configLoading, setConfigLoading] = useState(false);
    const [configSaving, setConfigSaving] = useState(false);
    const [form, setForm] = useState(emptyForm);
    const [roomId, setRoomId] = useState("");
    const [senderUserId, setSenderUserId] = useState("");
    const [packetType, setPacketType] = useState("");
    const [status, setStatus] = useState("");
    const [page, setPage] = useState(1);
    const [detailOpen, setDetailOpen] = useState(false);
    const [detailLoading, setDetailLoading] = useState(false);
    const [selectedPacket, setSelectedPacket] = useState(null);

    const filters = useMemo(
        () => ({
            roomId: roomId.trim() || undefined,
            senderUserId: senderUserId.trim() || undefined,
            packetMode: packetType || undefined,
            status: status || undefined,
        }),
        [packetType, roomId, senderUserId, status],
    );

    const {
        data: packets = emptyPackets,
        error: packetsError,
        loading: packetsLoading,
        reload: reloadPackets,
    } = usePaginatedQuery({
        errorMessage: "加载红包列表失败",
        fetcher: listRedPackets,
        filters,
        page,
        pageSize,
        queryKey: ["red-packets", filters, page],
    });

    const reloadConfig = useCallback(async () => {
        setConfigLoading(true);
        try {
            const config = await getRedPacketConfig();
            setConfig(config);
            setForm(formFromConfig(config));
        } catch (err) {
            showToast(err.message || "加载红包配置失败", "error");
        } finally {
            setConfigLoading(false);
        }
    }, [showToast]);

    useEffect(() => {
        void reloadConfig();
    }, [reloadConfig]);

    const openConfigDrawer = useCallback(() => {
        setForm(config ? formFromConfig(config) : emptyForm);
        setConfigDrawerOpen(true);
    }, [config]);

    const closeConfigDrawer = useCallback(() => {
        setConfigDrawerOpen(false);
        setForm(config ? formFromConfig(config) : emptyForm);
    }, [config]);

    const submitConfig = async (event) => {
        event.preventDefault();
        if (!abilities.canUpdate) {
            return;
        }
        setConfigSaving(true);
        try {
            const saved = await updateRedPacketConfig(payloadFromForm(form));
            setConfig(saved);
            setForm(formFromConfig(saved));
            setConfigDrawerOpen(false);
            showToast("红包配置已保存", "success");
        } catch (err) {
            showToast(err.message || "保存红包配置失败", "error");
        } finally {
            setConfigSaving(false);
        }
    };

    const openPacketDetail = async (packetId) => {
        if (!packetId) {
            return;
        }
        setDetailOpen(true);
        setDetailLoading(true);
        try {
            const packet = await getRedPacket(packetId);
            setSelectedPacket(packet);
        } catch (err) {
            showToast(err.message || "加载红包详情失败", "error");
        } finally {
            setDetailLoading(false);
        }
    };

    const retryRefund = async (packetId) => {
        if (!packetId || !abilities.canUpdate) {
            return;
        }
        try {
            await retryRedPacketRefund(packetId);
            showToast("退款重试已提交", "success");
            await reloadPackets();
            if (selectedPacket?.packetId === packetId) {
                await openPacketDetail(packetId);
            }
        } catch (err) {
            showToast(err.message || "退款重试失败", "error");
        }
    };

    const closePacketDetail = () => {
        setDetailOpen(false);
        setSelectedPacket(null);
    };

    const changeFilter = (setter) => (value) => {
        setter(value);
        setPage(1);
    };

    const resetFilters = () => {
        setRoomId("");
        setSenderUserId("");
        setPacketType("");
        setStatus("");
        setPage(1);
    };

    return {
        abilities,
        closeConfigDrawer,
        closePacketDetail,
        config,
        configDrawerOpen,
        configLoading,
        configSaving,
        detailLoading,
        detailOpen,
        form,
        openConfigDrawer,
        openPacketDetail,
        packetType,
        packets,
        packetsError,
        packetsLoading,
        page,
        reloadConfig,
        reloadPackets,
        resetFilters,
        retryRefund,
        roomId,
        selectedPacket,
        senderUserId,
        setForm,
        setPacketType: changeFilter(setPacketType),
        setPage,
        setRoomId: changeFilter(setRoomId),
        setSenderUserId: changeFilter(setSenderUserId),
        setStatus: changeFilter(setStatus),
        status,
        submitConfig,
    };
}

function formFromConfig(config) {
    return {
        enabled: Boolean(config.enabled),
        countTiers: valuesToForm(config.countTiers),
        amountTiers: valuesToForm(config.amountTiers),
        delayedOpenSeconds: String(config.delayedOpenSeconds || 0),
        expireSeconds: "86400",
        dailySendLimit: String(config.dailySendLimit || 0),
        ruleUrl: config.ruleUrl || "",
    };
}

function valuesToForm(values) {
    return values?.length ? values.map((value) => String(value)) : [""];
}

function payloadFromForm(form) {
    const countTiers = normalizePositiveIntegers(form.countTiers);
    const amountTiers = normalizePositiveIntegers(form.amountTiers);
    const delayedOpenSeconds = Number(form.delayedOpenSeconds || 0);
    const expireSeconds = 86400;
    const dailySendLimit = Number(form.dailySendLimit || 0);
    if (!countTiers.length) {
        throw new Error("红包数量档位不能为空");
    }
    if (!amountTiers.length) {
        throw new Error("红包金额档位不能为空");
    }
    if (!Number.isFinite(delayedOpenSeconds) || delayedOpenSeconds < 0) {
        throw new Error("延迟秒数不能小于 0");
    }
    if (!Number.isFinite(expireSeconds) || expireSeconds <= delayedOpenSeconds) {
        throw new Error("过期秒数必须大于延迟秒数");
    }
    if (!Number.isFinite(dailySendLimit) || dailySendLimit <= 0) {
        throw new Error("每日发送次数必须大于 0");
    }
    return {
        enabled: Boolean(form.enabled),
        count_tiers: countTiers,
        amount_tiers: amountTiers,
        delayed_open_seconds: delayedOpenSeconds,
        expire_seconds: expireSeconds,
        daily_send_limit: dailySendLimit,
        rule_url: String(form.ruleUrl || "").trim(),
    };
}

function normalizePositiveIntegers(values) {
    const seen = new Set();
    return (values || [])
        .map((value) => Number(value || 0))
        .filter((value) => Number.isInteger(value) && value > 0)
        .filter((value) => {
            if (seen.has(value)) {
                return false;
            }
            seen.add(value);
            return true;
        })
        .sort((a, b) => a - b);
}
