import { useEffect, useMemo, useState } from "react";
import {
    listThirdPartyPaymentChannels,
    syncThirdPartyPaymentMethods,
    setThirdPartyPaymentMethodStatus,
    syncThirdPartyPaymentRates,
    updateThirdPartyPaymentRate,
} from "@/features/payment/api";
import { usePaymentAbilities } from "@/features/payment/permissions.js";
import { thirdPartyPaymentRateSyncSchema } from "@/features/payment/schema";
import { useAdminQuery } from "@/shared/hooks/useAdminQuery.js";
import { useToast } from "@/shared/ui/ToastProvider.jsx";

const emptyChannels = { items: [], total: 0 };
const defaultSyncRateForm = { markupPercent: "0" };

export function useThirdPartyPaymentPage() {
    const abilities = usePaymentAbilities();
    const { showToast } = useToast();
    const [expandedChannel, setExpandedChannel] = useState("");
    const [loadingAction, setLoadingAction] = useState("");
    const [rateDrafts, setRateDrafts] = useState({});
    const [syncRateDialogOpen, setSyncRateDialogOpen] = useState(false);
    const [syncRateForm, setSyncRateFormState] = useState(defaultSyncRateForm);

    // 三方支付页是配置中心入口，列表必须包含已关闭方式，H5 只展示后端判定可用的方式。
    // 这里不在前端过滤关闭项，保证运营可以重新打开某个国家或某个支付方式。
    const result = useAdminQuery(listThirdPartyPaymentChannels, {
        errorMessage: "加载第三方支付失败",
        initialData: emptyChannels,
        queryKey: ["payment", "third-party-channels"],
    });

    // 后端按 providerCode 返回渠道；展开态只保存 code，避免列表刷新后持有旧对象。
    const channels = useMemo(() => result.data?.items || [], [result.data]);
    const activeChannelCode = expandedChannel || channels[0]?.providerCode || "";
    const activeChannel = useMemo(
        () => channels.find((channel) => channel.providerCode === activeChannelCode) || channels[0] || null,
        [activeChannelCode, channels],
    );

    // 默认打开第一条渠道，让运营进页面即可看到国家/方式明细；没有渠道时保持空态。
    useEffect(() => {
        if (!expandedChannel && channels[0]?.providerCode) {
            setExpandedChannel(channels[0].providerCode);
        }
    }, [channels, expandedChannel]);

    // 汇率输入是可编辑草稿，不能直接绑定服务端对象，否则用户输入中途刷新会覆盖正在编辑的值。
    // 只在本地没有草稿时用接口值初始化，保存后再通过 reload 收敛到服务端事实。
    useEffect(() => {
        setRateDrafts((current) => {
            const next = { ...current };
            channels.forEach((channel) => {
                (channel.methods || []).forEach((method) => {
                    const key = String(method.methodId);
                    if (next[key] === undefined) {
                        next[key] = method.usdToCurrencyRate || "";
                    }
                });
            });
            return next;
        });
    }, [channels]);

    const toggleChannel = (channelCode) => {
        setExpandedChannel((current) => (current === channelCode ? "" : channelCode));
    };

    const setRateDraft = (methodId, value) => {
        setRateDrafts((current) => ({ ...current, [String(methodId)]: value }));
    };

    const setSyncRateMarkupPercent = (value) => {
        setSyncRateFormState({ markupPercent: value });
    };

    const openSyncRateDialog = () => {
        if (!abilities.canUpdateThirdParty) {
            return;
        }
        setSyncRateFormState(defaultSyncRateForm);
        setSyncRateDialogOpen(true);
    };

    const closeSyncRateDialog = () => {
        // 同步请求已经开始后不允许关闭弹窗，避免运营误判请求被取消；接口返回后统一由成功/失败提示收敛状态。
        if (loadingAction === "sync-rates") {
            return;
        }
        setSyncRateDialogOpen(false);
    };

    const syncPaymentMethods = async (channel) => {
        // 支付方式同步只开放给 V5Pay；MiFaPay 暂无可查询当前商户已开通方式的后端接口。
        if (!abilities.canUpdateThirdParty || channel?.providerCode !== "v5pay") {
            return;
        }
        const actionKey = `sync-methods:${channel.providerCode}`;
        setLoadingAction(actionKey);
        try {
            const summary = await syncThirdPartyPaymentMethods({ providerCode: channel.providerCode });
            const fresh = await result.reload();
            setRateDrafts(rateDraftsFromChannels(fresh?.items || []));
            showToast(paymentMethodSyncToast(summary), summary?.failedCountryCount ? "warning" : "success");
        } catch (err) {
            showToast(err.message || "同步支付方式失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    const toggleMethod = async (method, active) => {
        // 权限判断放在动作入口，避免只依赖按钮禁用；接口失败时保留原状态并提示。
        if (!abilities.canUpdateThirdParty) {
            return;
        }
        const actionKey = `status:${method.methodId}`;
        setLoadingAction(actionKey);
        try {
            await setThirdPartyPaymentMethodStatus(method.methodId, { enabled: active });
            await result.reload();
            showToast(active ? "支付方式已打开" : "支付方式已关闭", "success");
        } catch (err) {
            showToast(err.message || "状态更新失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    const saveRate = async (method) => {
        // 汇率决定 H5 展示和下单本币金额，前端先挡掉空值和非正数，最终仍以后端校验为准。
        if (!abilities.canUpdateThirdParty) {
            return;
        }
        const rateToUsd = String(rateDrafts[String(method.methodId)] || "").trim();
        if (!rateToUsd || Number(rateToUsd) <= 0) {
            showToast("请填写大于 0 的汇率", "error");
            return;
        }
        const actionKey = `rate:${method.methodId}`;
        setLoadingAction(actionKey);
        try {
            await updateThirdPartyPaymentRate(method.methodId, { usdToCurrencyRate: rateToUsd });
            await result.reload();
            showToast("汇率已保存", "success");
        } catch (err) {
            showToast(err.message || "汇率保存失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    const submitSyncRates = async (event) => {
        event?.preventDefault();
        // 上浮比例只表达运营策略，不在前端计算最终汇率；服务端会拉实时源、套用比例并按高汇率整数规则向上取整，避免旧页面数据参与写库。
        if (!abilities.canUpdateThirdParty) {
            return;
        }
        const parsed = thirdPartyPaymentRateSyncSchema.safeParse(syncRateForm);
        if (!parsed.success) {
            showToast(parsed.error.issues[0]?.message || "汇率同步参数不正确", "error");
            return;
        }
        setLoadingAction("sync-rates");
        try {
            const summary = await syncThirdPartyPaymentRates({ markupPercent: parsed.data.markupPercent });
            const fresh = await result.reload();
            setRateDrafts(rateDraftsFromChannels(fresh?.items || []));
            setSyncRateDialogOpen(false);
            const suffix = summary?.sourceNames?.length ? `（${summary.sourceNames.join("、")}）` : "";
            showToast(`汇率已同步 ${summary?.updatedCount || 0} 个支付方式${suffix}`, "success");
        } catch (err) {
            showToast(err.message || "汇率同步失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    return {
        abilities,
        activeChannel,
        channels,
        closeSyncRateDialog,
        error: result.error,
        expandedChannel,
        loading: result.loading,
        loadingAction,
        openSyncRateDialog,
        rateDrafts,
        reload: result.reload,
        saveRate,
        setRateDraft,
        setSyncRateMarkupPercent,
        syncPaymentMethods,
        submitSyncRates,
        syncRateDialogOpen,
        syncRateForm,
        toggleChannel,
        toggleMethod,
    };
}

function rateDraftsFromChannels(channels) {
    return channels.reduce((drafts, channel) => {
        (channel.methods || []).forEach((method) => {
            drafts[String(method.methodId)] = method.usdToCurrencyRate || "";
        });
        return drafts;
    }, {});
}

function paymentMethodSyncToast(summary = {}) {
    const created = summary.createdCount || 0;
    const updated = summary.updatedCount || 0;
    const failed = summary.failedCountryCount || 0;
    const skipped = summary.skippedCount || 0;
    const suffix = failed ? `，失败 ${failed} 个国家` : "";
    const skippedSuffix = skipped ? `，跳过 ${skipped} 个方式` : "";
    return `支付方式已同步：新增 ${created} 个，更新 ${updated} 个${skippedSuffix}${suffix}`;
}
