import { useCallback, useDeferredValue, useEffect, useMemo, useState } from "react";
import { useAppScope } from "@/app/app-scope/AppScopeProvider.jsx";
import {
    exportActivityTemplateData,
    getActivityTemplateData,
    listActivityTemplateLeaderboard,
    listActivityTemplateRewardJobs,
    listActivityTemplateTaskClaims,
    listActivityTemplateVersions,
    retryActivityTemplateRewardJob,
    retryActivityTemplateTaskClaim,
} from "@/features/activity-templates/api";
import {
    activityDailyPeriodOptions,
    activityTemplateForRuntime,
    createActivityDataInitialRange,
    defaultActivityDailyPeriod,
    downloadActivityTemplateDataCsv,
    normalizeActivityDataUtcRange,
} from "@/features/activity-templates/dataModel.js";
import { useAdminQuery } from "@/shared/hooks/useAdminQuery.js";
import { useConfirm } from "@/shared/ui/ConfirmProvider.jsx";
import { useToast } from "@/shared/ui/ToastProvider.jsx";

const PAGE_SIZE = 20;
const VERSION_PAGE_SIZE = 100;
const VERSION_LIMIT = 1000;
const emptyVersions = { items: [], page: 1, pageSize: VERSION_PAGE_SIZE, total: 0 };
const emptyData = {
    overview: {},
    trend: [],
    gifts: [],
    tasks: [],
    granularity: "day",
    timezone: "UTC",
    startMs: 0,
    endMs: 0,
    regionId: 0,
};
const emptyLeaderboard = { items: [], page: 1, pageSize: PAGE_SIZE, period: {}, total: 0 };
const emptyRewards = { items: [], page: 1, pageSize: PAGE_SIZE, total: 0 };
const emptyTaskClaims = { items: [], page: 1, pageSize: PAGE_SIZE, total: 0 };

export function useActivityTemplateDataCenter({ abilities, regionOptions, source }) {
    const { appCode } = useAppScope();
    const confirm = useConfirm();
    const { showToast } = useToast();
    const [activeTab, setActiveTab] = useState("overview");
    const [versionNo, setVersionNo] = useState(0);
    const [regionId, setRegionId] = useState("");
    const [timeRange, setTimeRange] = useState({ endMs: "", startMs: "" });
    const [leaderboardBoardType, setLeaderboardBoardType] = useState("daily");
    const [leaderboardPeriodKey, setLeaderboardPeriodKey] = useState("");
    const [leaderboardPage, setLeaderboardPage] = useState(1);
    const [rewardBoardType, setRewardBoardType] = useState("");
    const [rewardPeriodKey, setRewardPeriodKey] = useState("");
    const [rewardStatus, setRewardStatus] = useState("");
    const [rewardPage, setRewardPage] = useState(1);
    const [taskClaimDay, setTaskClaimDay] = useState("");
    const [taskClaimKey, setTaskClaimKey] = useState("");
    const [taskClaimUserId, setTaskClaimUserId] = useState("");
    const [taskClaimStatus, setTaskClaimStatus] = useState("");
    const [taskClaimPage, setTaskClaimPage] = useState(1);
    const [loadingAction, setLoadingAction] = useState("");
    const deferredTaskClaimUserId = useDeferredValue(taskClaimUserId);

    useEffect(() => {
        if (!source?.templateId) return;
        const nextVersion = Number(source.publishedVersion || 0);
        setActiveTab("overview");
        setVersionNo(nextVersion);
        setRegionId("");
        setTimeRange(createActivityDataInitialRange(source));
        setLeaderboardBoardType("daily");
        setLeaderboardPeriodKey(defaultActivityDailyPeriod(source));
        setLeaderboardPage(1);
        setRewardBoardType("");
        setRewardPeriodKey("");
        setRewardStatus("");
        setRewardPage(1);
        setTaskClaimDay("");
        setTaskClaimKey("");
        setTaskClaimUserId("");
        setTaskClaimStatus("");
        setTaskClaimPage(1);
        setLoadingAction("");
    }, [source]);

    const versionsQueryFn = useCallback(() => loadAllVersions(source?.templateId), [source?.templateId]);
    const {
        data: versions = emptyVersions,
        error: versionsError,
        loading: versionsLoading,
        reload: reloadVersions,
    } = useAdminQuery(versionsQueryFn, {
        enabled: Boolean(source?.templateId),
        errorMessage: "加载发布版本失败",
        initialData: emptyVersions,
        queryKey: ["activity-template-data-versions", appCode, source?.templateId],
        staleTime: 60 * 1000,
    });

    const versionItems = useMemo(() => {
        const items = [...(versions.items || [])];
        const currentVersion = Number(source?.publishedVersion || 0);
        if (currentVersion > 0 && !items.some((item) => Number(item.versionNo) === currentVersion)) {
            items.push({ snapshot: source, templateId: source.templateId, versionNo: currentVersion });
        }
        return items.sort((left, right) => Number(right.versionNo) - Number(left.versionNo));
    }, [source, versions.items]);
    const selectedVersion = useMemo(
        () => versionItems.find((item) => Number(item.versionNo) === Number(versionNo)),
        [versionItems, versionNo],
    );
    const selectedTemplate = useMemo(
        () => activityTemplateForRuntime(selectedVersion, source),
        [selectedVersion, source],
    );
    const selectedRuntimeStartMs = selectedTemplate.startMs;
    const selectedRuntimeEndMs = selectedTemplate.endMs;
    useEffect(() => {
        if (!source?.templateId || versionNo <= 0) return;
        if (!Number(selectedVersion?.runtimeFromMs || 0) && !Number(selectedVersion?.runtimeToMs || 0)) return;
        // 版本列表异步返回后再把初始筛选从计划窗口校准到实际运行窗口；依赖只含窗口原值，
        // 用户随后手动调整时间不会被后台 refetch 或对象引用变化覆盖。
        const runtimeWindow = { endMs: selectedRuntimeEndMs, startMs: selectedRuntimeStartMs };
        setTimeRange(createActivityDataInitialRange(runtimeWindow));
        setLeaderboardPeriodKey(defaultActivityDailyPeriod(runtimeWindow));
        setLeaderboardPage(1);
    }, [
        selectedRuntimeEndMs,
        selectedRuntimeStartMs,
        selectedVersion?.runtimeFromMs,
        selectedVersion?.runtimeToMs,
        source?.templateId,
        versionNo,
    ]);
    const periodOptions = useMemo(() => activityDailyPeriodOptions(selectedTemplate), [selectedTemplate]);
    const scopedRegionOptions = useMemo(() => {
        if (selectedTemplate.allRegions) return regionOptions;
        const allowed = new Set((selectedTemplate.regionIds || []).map(String));
        return regionOptions.filter((item) => allowed.has(String(item.value)));
    }, [regionOptions, selectedTemplate.allRegions, selectedTemplate.regionIds]);

    const normalizedRange = useMemo(() => normalizeActivityDataUtcRange(timeRange), [timeRange]);
    const dataParams = useMemo(
        () =>
            normalizedRange && versionNo > 0
                ? {
                      ...normalizedRange,
                      region_id: regionId || undefined,
                      version_no: versionNo,
                  }
                : null,
        [normalizedRange, regionId, versionNo],
    );
    const dataQueryFn = useCallback(
        () => getActivityTemplateData(source?.templateId, dataParams),
        [dataParams, source?.templateId],
    );
    const {
        data = emptyData,
        error: dataError,
        loading: dataLoading,
        reload: reloadData,
    } = useAdminQuery(dataQueryFn, {
        enabled: Boolean(source?.templateId && abilities.canData && dataParams),
        errorMessage: "加载活动统计失败",
        initialData: emptyData,
        keepPreviousData: true,
        queryKey: ["activity-template-data", appCode, source?.templateId, dataParams],
    });

    const leaderboardParams = useMemo(
        () => ({
            board_type: leaderboardBoardType,
            page: leaderboardPage,
            page_size: PAGE_SIZE,
            period_key: leaderboardBoardType === "total" ? "total" : leaderboardPeriodKey,
            version_no: versionNo,
        }),
        [leaderboardBoardType, leaderboardPage, leaderboardPeriodKey, versionNo],
    );
    const leaderboardQueryFn = useCallback(
        () => listActivityTemplateLeaderboard(source?.templateId, leaderboardParams),
        [leaderboardParams, source?.templateId],
    );
    const {
        data: leaderboard = emptyLeaderboard,
        error: leaderboardError,
        loading: leaderboardLoading,
        reload: reloadLeaderboard,
    } = useAdminQuery(leaderboardQueryFn, {
        enabled: Boolean(
            source?.templateId &&
            abilities.canData &&
            versionNo > 0 &&
            activeTab === "leaderboard" &&
            (leaderboardBoardType === "total" || leaderboardPeriodKey),
        ),
        errorMessage: "加载活动榜单失败",
        initialData: emptyLeaderboard,
        keepPreviousData: true,
        queryKey: ["activity-template-leaderboard", appCode, source?.templateId, leaderboardParams],
    });

    const rewardParams = useMemo(
        () => ({
            board_type: rewardBoardType || undefined,
            page: rewardPage,
            page_size: PAGE_SIZE,
            period_key: rewardBoardType === "total" ? "total" : rewardPeriodKey || undefined,
            status: rewardStatus || undefined,
            version_no: versionNo,
        }),
        [rewardBoardType, rewardPage, rewardPeriodKey, rewardStatus, versionNo],
    );
    const rewardQueryFn = useCallback(
        () => listActivityTemplateRewardJobs(source?.templateId, rewardParams),
        [rewardParams, source?.templateId],
    );
    const {
        data: rewards = emptyRewards,
        error: rewardsError,
        loading: rewardsLoading,
        reload: reloadRewards,
    } = useAdminQuery(rewardQueryFn, {
        enabled: Boolean(source?.templateId && abilities.canData && versionNo > 0 && activeTab === "rewards"),
        errorMessage: "加载奖励发放记录失败",
        initialData: emptyRewards,
        keepPreviousData: true,
        queryKey: ["activity-template-rewards", appCode, source?.templateId, rewardParams],
    });

    const taskClaimParams = useMemo(
        () => ({
            page: taskClaimPage,
            page_size: PAGE_SIZE,
            status: taskClaimStatus || undefined,
            task_day: taskClaimDay || undefined,
            task_key: taskClaimKey || undefined,
            user_id: deferredTaskClaimUserId || undefined,
            version_no: versionNo,
        }),
        [deferredTaskClaimUserId, taskClaimDay, taskClaimKey, taskClaimPage, taskClaimStatus, versionNo],
    );
    const taskClaimsQueryFn = useCallback(
        () => listActivityTemplateTaskClaims(source?.templateId, taskClaimParams),
        [source?.templateId, taskClaimParams],
    );
    const {
        data: taskClaims = emptyTaskClaims,
        error: taskClaimsError,
        loading: taskClaimsLoading,
        reload: reloadTaskClaims,
    } = useAdminQuery(taskClaimsQueryFn, {
        enabled: Boolean(source?.templateId && abilities.canData && versionNo > 0 && activeTab === "taskClaims"),
        errorMessage: "加载任务领奖记录失败",
        initialData: emptyTaskClaims,
        keepPreviousData: true,
        queryKey: ["activity-template-task-claims", appCode, source?.templateId, taskClaimParams],
    });

    const changeVersion = (nextVersion) => {
        const normalizedVersion = Number(nextVersion);
        const nextVersionItem = versionItems.find((item) => Number(item.versionNo) === normalizedVersion);
        const nextTemplate = activityTemplateForRuntime(nextVersionItem, source);
        setVersionNo(normalizedVersion);
        setRegionId("");
        setTimeRange(createActivityDataInitialRange(nextTemplate));
        setLeaderboardPeriodKey(defaultActivityDailyPeriod(nextTemplate));
        setLeaderboardPage(1);
        setRewardPeriodKey("");
        setRewardPage(1);
        setTaskClaimDay("");
        setTaskClaimKey("");
        setTaskClaimUserId("");
        setTaskClaimPage(1);
    };
    const changeLeaderboardBoardType = (value) => {
        setLeaderboardBoardType(value);
        setLeaderboardPage(1);
        if (value === "daily" && !leaderboardPeriodKey) {
            setLeaderboardPeriodKey(defaultActivityDailyPeriod(selectedTemplate));
        }
    };
    const changeRewardBoardType = (value) => {
        setRewardBoardType(value);
        setRewardPeriodKey("");
        setRewardPage(1);
    };
    const exportData = async () => {
        if (!dataParams || !source?.templateId || loadingAction) return;
        setLoadingAction("export");
        try {
            // 导出端点复用统计服务的受限聚合查询，必须使用它的实际响应生成文件，
            // 不能从当前 UI 表格拼接，否则 Top100、UTC 窗口和区域回显可能与后端审计记录不一致。
            const exported = await exportActivityTemplateData(source.templateId, dataParams);
            const dateStamp = new Date().toISOString().slice(0, 10);
            downloadActivityTemplateDataCsv(
                exported,
                `activity-template-${source.templateCode || source.templateId}-v${versionNo}-${dateStamp}.csv`,
            );
            showToast("活动数据已导出", "success");
        } catch (error) {
            showToast(error.message || "导出活动数据失败", "error");
        } finally {
            setLoadingAction("");
        }
    };
    const retryReward = async (job) => {
        if (!source?.templateId || !["failed", "dead"].includes(job.status) || loadingAction) return;
        const ok = await confirm({
            confirmText: "重新发放",
            message: `奖励任务 ${job.rewardJobId} 将使用原钱包命令幂等重试。`,
            title: "重试奖励发放",
        });
        if (!ok) return;
        setLoadingAction(`retry:${job.rewardJobId}`);
        try {
            await retryActivityTemplateRewardJob(source.templateId, job.rewardJobId);
            showToast("奖励重试已提交", "success");
            await reloadRewards();
        } catch (error) {
            showToast(error.message || "奖励重试失败", "error");
        } finally {
            setLoadingAction("");
        }
    };
    const retryTaskClaim = async (claim) => {
        if (!source?.templateId || claim.status !== "failed" || loadingAction) return;
        const ok = await confirm({
            confirmText: "重新发放",
            message: `任务 ${claim.taskKey} 的领奖记录 ${claim.claimId} 将使用原钱包命令幂等重试。`,
            title: "重试任务奖励",
        });
        if (!ok) return;
        setLoadingAction(`retry-claim:${claim.claimId}`);
        try {
            await retryActivityTemplateTaskClaim(source.templateId, claim.claimId);
            showToast("任务奖励重试已提交", "success");
            await reloadTaskClaims();
        } catch (error) {
            showToast(error.message || "任务奖励重试失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    return {
        activeTab,
        changeLeaderboardBoardType,
        changeRewardBoardType,
        changeVersion,
        data,
        dataError,
        dataLoading,
        dataParams,
        exportData,
        leaderboard,
        leaderboardBoardType,
        leaderboardError,
        leaderboardLoading,
        leaderboardPage,
        leaderboardPeriodKey,
        loadingAction,
        periodOptions,
        regionId,
        reloadData,
        reloadLeaderboard,
        reloadRewards,
        reloadTaskClaims,
        reloadVersions,
        retryReward,
        retryTaskClaim,
        rewardBoardType,
        rewardPage,
        rewardPeriodKey,
        rewards,
        rewardsError,
        rewardsLoading,
        rewardStatus,
        scopedRegionOptions,
        selectedTemplate,
        selectedVersion,
        setActiveTab,
        setLeaderboardPage,
        setLeaderboardPeriodKey: (value) => {
            setLeaderboardPeriodKey(value);
            setLeaderboardPage(1);
        },
        setRegionId,
        setRewardPage,
        setRewardPeriodKey: (value) => {
            setRewardPeriodKey(value);
            setRewardPage(1);
        },
        setRewardStatus: (value) => {
            setRewardStatus(value);
            setRewardPage(1);
        },
        setTimeRange,
        setTaskClaimDay: (value) => {
            setTaskClaimDay(value);
            setTaskClaimPage(1);
        },
        setTaskClaimKey: (value) => {
            setTaskClaimKey(value);
            setTaskClaimPage(1);
        },
        setTaskClaimPage,
        setTaskClaimStatus: (value) => {
            setTaskClaimStatus(value);
            setTaskClaimPage(1);
        },
        setTaskClaimUserId: (value) => {
            setTaskClaimUserId(String(value || "").replace(/\D/g, ""));
            setTaskClaimPage(1);
        },
        taskClaimDay,
        taskClaimKey,
        taskClaimPage,
        taskClaims,
        taskClaimsError,
        taskClaimsLoading,
        taskClaimStatus,
        taskClaimUserId,
        timeRange,
        versionItems,
        versionNo,
        versionsError,
        versionsLoading,
    };
}

async function loadAllVersions(templateId) {
    if (!templateId) return emptyVersions;
    const items = [];
    let page = 1;
    let total;
    do {
        const result = await listActivityTemplateVersions(templateId, { page, page_size: VERSION_PAGE_SIZE });
        items.push(...(result.items || []));
        total = Number(result.total || items.length);
        if (!(result.items || []).length) break;
        page += 1;
    } while (items.length < total && items.length < VERSION_LIMIT);
    return { items: items.slice(0, VERSION_LIMIT), page: 1, pageSize: VERSION_PAGE_SIZE, total };
}
