import { useCallback, useEffect, useMemo, useState } from "react";
import { parseForm } from "@/shared/forms/validation";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import { listResourceGroups, listResources } from "@/features/resources/api";
import { levelTrackLabels } from "@/features/level-config/constants.js";
import {
    batchUpsertLevelConfig,
    createTier,
    listLevelConfig,
    updateTier,
    updateTrack,
    upsertRule,
} from "@/features/level-config/api";
import { useLevelConfigAbilities } from "@/features/level-config/permissions.js";
import { levelRuleFormSchema, levelTierFormSchema, levelTrackFormSchema } from "@/features/level-config/schema";

const emptyConfig = { serverTimeMs: 0, tracks: [] };
const defaultTrack = "wealth";
const resourcePageQuery = { page: 1, page_size: 500, status: "active" };
const badgeResourcePageQuery = { ...resourcePageQuery, resource_type: "badge" };
const avatarFrameResourcePageQuery = { ...resourcePageQuery, resource_type: "avatar_frame" };

export function useLevelConfigPage() {
    const abilities = useLevelConfigAbilities();
    const { showToast } = useToast();
    const [config, setConfig] = useState(emptyConfig);
    const [resources, setResources] = useState([]);
    const [badgeResources, setBadgeResources] = useState([]);
    const [avatarFrameResources, setAvatarFrameResources] = useState([]);
    const [resourceGroups, setResourceGroups] = useState([]);
    const [track, setTrack] = useState(defaultTrack);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState("");
    const [activeAction, setActiveAction] = useState("");
    const [selectedRule, setSelectedRule] = useState(null);
    const [selectedTier, setSelectedTier] = useState(null);
    const [selectedTrack, setSelectedTrack] = useState(null);
    const [ruleForm, setRuleForm] = useState(() => buildRuleForm());
    const [tierForm, setTierForm] = useState(() => buildTierForm());
    const [trackForm, setTrackForm] = useState(() => buildTrackForm());
    const [batchForms, setBatchForms] = useState([]);
    const [batchOriginal, setBatchOriginal] = useState([]);
    const [loadingAction, setLoadingAction] = useState("");

    const reload = useCallback(async () => {
        setLoading(true);
        setError("");
        try {
            const [nextConfig, badgeResourcePage, avatarFrameResourcePage, groupPage] = await Promise.all([
                listLevelConfig(),
                // 等级配置只需要徽章和头像框；后端分页按类型过滤，避免 active 资源超过第一页时漏掉等级徽章。
                listResources(badgeResourcePageQuery),
                listResources(avatarFrameResourcePageQuery),
                listResourceGroups(resourcePageQuery),
            ]);
            const nextBadgeResources = badgeResourcePage.items || [];
            const nextAvatarFrameResources = avatarFrameResourcePage.items || [];
            setConfig(nextConfig);
            setBadgeResources(nextBadgeResources);
            setAvatarFrameResources(nextAvatarFrameResources);
            setResources([...nextBadgeResources, ...nextAvatarFrameResources]);
            setResourceGroups(groupPage.items || []);
        } catch (err) {
            setError(err.message || "加载等级配置失败");
        } finally {
            setLoading(false);
        }
    }, []);

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

    // 保存后只刷新配置数据，不切回整页骨架；滚动容器保持挂载才能保留用户当前位置。
    const refreshConfig = useCallback(async () => {
        const nextConfig = await listLevelConfig();
        setConfig(nextConfig);
        return nextConfig;
    }, []);

    const tracks = useMemo(() => (config.tracks || []).filter((item) => item.track === track), [config.tracks, track]);
    const changeTrack = (value) => setTrack(value);

    const openRuleCreate = (trackCode = resolveDefaultTrack(config, track)) => {
        setSelectedRule(null);
        setRuleForm(buildRuleForm(null, resolveTrack(config, trackCode)));
        setActiveAction("rule-create");
    };

    const openRuleEdit = (rule) => {
        setSelectedRule(rule);
        setRuleForm(buildRuleForm(rule));
        setActiveAction("rule-edit");
    };

    const openTierCreate = (trackCode = resolveDefaultTrack(config, track)) => {
        setSelectedTier(null);
        setTierForm(buildTierForm(null, resolveTrack(config, trackCode)));
        setActiveAction("tier-create");
    };

    const openTierEdit = (tier) => {
        setSelectedTier(tier);
        setTierForm(buildTierForm(tier));
        setActiveAction("tier-edit");
    };

    const openTrackEdit = (levelTrack) => {
        setSelectedTrack(levelTrack);
        setTrackForm(buildTrackForm(levelTrack));
        setActiveAction("track-edit");
    };

    const openRuleBatchEdit = (levelTrack) => {
        const forms = (levelTrack?.rules || []).map((rule) => buildRuleForm(rule));
        setBatchForms(forms);
        setBatchOriginal(forms);
        setActiveAction("rule-batch-edit");
    };

    const openTierBatchEdit = (levelTrack) => {
        const forms = (levelTrack?.tiers || []).map((tier) => ({ ...buildTierForm(tier), tierId: tier.tierId }));
        setBatchForms(forms);
        setBatchOriginal(forms);
        setActiveAction("tier-batch-edit");
    };

    const closeAction = () => {
        setActiveAction("");
        setSelectedRule(null);
        setSelectedTier(null);
        setSelectedTrack(null);
        setBatchForms([]);
        setBatchOriginal([]);
    };

    const submitRule = async (event) => {
        event.preventDefault();
        const editing = activeAction === "rule-edit";
        const parsed = parseForm(levelRuleFormSchema, ruleForm);
        const level = Number(parsed.level);
        await runAction(
            editing ? "rule-edit" : "rule-create",
            editing ? "等级规则已更新" : "等级规则已创建",
            async () => {
                await upsertRule(parsed.track, level, buildRulePayload(parsed));
                closeAction();
                await refreshConfig();
            },
        );
    };

    const submitTier = async (event) => {
        event.preventDefault();
        const editing = activeAction === "tier-edit";
        if (editing && !selectedTier?.tierId) {
            return;
        }
        const parsed = parseForm(levelTierFormSchema, tierForm);
        await runAction(editing ? "tier-edit" : "tier-create", editing ? "等级层已更新" : "等级层已创建", async () => {
            const payload = buildTierPayload(parsed);
            if (editing) {
                await updateTier(selectedTier.tierId, payload);
            } else {
                await createTier(payload);
            }
            closeAction();
            await refreshConfig();
        });
    };

    const submitTrack = async (event) => {
        event.preventDefault();
        if (!selectedTrack?.track) {
            return;
        }
        const parsed = parseForm(levelTrackFormSchema, trackForm);
        await runAction("track-edit", "等级类型已更新", async () => {
            await updateTrack(selectedTrack.track, buildTrackPayload(parsed));
            closeAction();
            await refreshConfig();
        });
    };

    const toggleRule = async (rule, nextEnabled = rule.status !== "active") => {
        if (!abilities.canUpdate || !rule?.track || rule?.level === undefined || rule?.level === null) {
            return;
        }
        const nextStatus = nextEnabled ? "active" : "disabled";
        if (rule.status === nextStatus) {
            return;
        }
        await runAction(
            `rule-status-${rule.track}-${rule.level}`,
            nextEnabled ? "等级规则已启用" : "等级规则已停用",
            async () => {
                await upsertRule(
                    rule.track,
                    rule.level,
                    buildRulePayload(buildRuleForm({ ...rule, status: nextStatus })),
                );
                await refreshConfig();
            },
        );
    };

    const toggleTier = async (tier, nextEnabled = tier.status !== "active") => {
        if (!abilities.canUpdate || !tier?.tierId) {
            return;
        }
        const nextStatus = nextEnabled ? "active" : "disabled";
        if (tier.status === nextStatus) {
            return;
        }
        await runAction(`tier-status-${tier.tierId}`, nextEnabled ? "等级层已启用" : "等级层已停用", async () => {
            await updateTier(tier.tierId, buildTierPayload(buildTierForm({ ...tier, status: nextStatus })));
            await refreshConfig();
        });
    };

    const updateBatchForm = (index, key, value) => {
        setBatchForms((current) =>
            current.map((form, formIndex) => (formIndex === index ? { ...form, [key]: value } : form)),
        );
    };

    const submitRuleBatch = async (event) => {
        event.preventDefault();
        await runAction("rule-batch-edit", "等级规则已批量更新", async () => {
            const rules = batchForms
                .filter((form, index) => !sameForm(form, batchOriginal[index]))
                .map((form) => {
                    const parsed = parseForm(levelRuleFormSchema, form);
                    return { ...buildRulePayload(parsed), level: Number(parsed.level), track: parsed.track };
                });
            if (!rules.length) {
                throw new Error("没有需要保存的修改");
            }
            await batchUpsertLevelConfig({ rules, tiers: [] });
            closeAction();
            await refreshConfig();
        });
    };

    const submitTierBatch = async (event) => {
        event.preventDefault();
        await runAction("tier-batch-edit", "等级层已批量更新", async () => {
            const tiers = batchForms
                .filter((form, index) => !sameForm(form, batchOriginal[index]))
                .map((form) => {
                    const parsed = parseForm(levelTierFormSchema, form);
                    return { ...buildTierPayload(parsed), tier_id: Number(form.tierId) };
                });
            if (!tiers.length) {
                throw new Error("没有需要保存的修改");
            }
            await batchUpsertLevelConfig({ rules: [], tiers });
            closeAction();
            await refreshConfig();
        });
    };

    const batchDirty = useMemo(
        () => batchForms.some((form, index) => !sameForm(form, batchOriginal[index])),
        [batchForms, batchOriginal],
    );

    const runAction = async (action, successMessage, submitter) => {
        setLoadingAction(action);
        try {
            await submitter();
            showToast(successMessage, "success");
        } catch (err) {
            showToast(err.message || "操作失败", "error");
        } finally {
            setLoadingAction("");
        }
    };

    return {
        abilities,
        activeAction,
        avatarFrameResources,
        badgeResources,
        batchDirty,
        batchForms,
        changeTrack,
        closeAction,
        config,
        error,
        loading,
        loadingAction,
        openRuleCreate,
        openRuleBatchEdit,
        openRuleEdit,
        openTierCreate,
        openTierBatchEdit,
        openTierEdit,
        openTrackEdit,
        reload,
        resourceGroups,
        resources,
        ruleForm,
        selectedRule,
        selectedTier,
        selectedTrack,
        setRuleForm,
        setTierForm,
        setTrackForm,
        submitRule,
        submitRuleBatch,
        submitTier,
        submitTierBatch,
        submitTrack,
        tierForm,
        toggleRule,
        toggleTier,
        track,
        trackForm,
        tracks,
        updateBatchForm,
    };
}

function resolveDefaultTrack(config, selectedTrack) {
    if (selectedTrack) {
        return selectedTrack;
    }
    return config.tracks?.[0]?.track || defaultTrack;
}

function resolveTrack(config, trackCode) {
    return (config.tracks || []).find((item) => item.track === trackCode) || { track: trackCode, rules: [], tiers: [] };
}

function buildRuleForm(rule = null, levelTrack = null) {
    const nextLevel = rule ? rule.level : nextRuleLevel(levelTrack);
    const trackCode = rule?.track || levelTrack?.track || defaultTrack;
    return {
        avatarFrameResourceId: optionalId(rule?.avatarFrameResourceId),
        level: valueOrEmpty(nextLevel),
        longBadgeResourceId: optionalId(rule?.longBadgeResourceId),
        name: rule?.name || `${levelTrackLabels[trackCode] || "等级"} ${nextLevel}级`,
        requiredValue: valueOrEmpty(rule?.requiredValue),
        rewardResourceGroupId: optionalId(rule?.rewardResourceGroupId),
        shortBadgeResourceId: optionalId(rule?.shortBadgeResourceId),
        sortOrder: valueOrDefault(rule?.sortOrder, nextLevel),
        status: rule?.status || "active",
        track: trackCode,
    };
}

function buildTierForm(tier = null, levelTrack = null) {
    const minLevel = tier ? tier.minLevel : nextTierStart(levelTrack);
    const maxLevel = tier ? tier.maxLevel : minLevel + 9;
    const trackCode = tier?.track || levelTrack?.track || defaultTrack;
    return {
        displayAvatarFrameResourceId: optionalId(tier?.displayAvatarFrameResourceId),
        displayBadgeResourceId: optionalId(tier?.displayBadgeResourceId),
        displayConfigJson: tier?.displayConfigJson || "",
        maxLevel: valueOrEmpty(maxLevel),
        minLevel: valueOrEmpty(minLevel),
        name: tier?.name || `${levelTrackLabels[trackCode] || "等级"} ${minLevel}-${maxLevel}级`,
        rewardResourceGroupId: optionalId(tier?.rewardResourceGroupId),
        status: tier?.status || "active",
        track: trackCode,
    };
}

function buildTrackForm(levelTrack = null) {
    return {
        displayConfigJson: levelTrack?.displayConfigJson || "",
        name: levelTrack?.name || (levelTrack?.track ? levelTrackLabels[levelTrack.track] : ""),
        sortOrder: valueOrDefault(levelTrack?.sortOrder, 0),
        status: levelTrack?.status || "active",
    };
}

function buildRulePayload(form) {
    return {
        avatar_frame_resource_id: Number(form.avatarFrameResourceId || 0),
        long_badge_resource_id: Number(form.longBadgeResourceId || 0),
        name: String(form.name || "").trim(),
        required_value: Number(form.requiredValue || 0),
        reward_resource_group_id: Number(form.rewardResourceGroupId || 0),
        short_badge_resource_id: Number(form.shortBadgeResourceId || 0),
        sort_order: Number(form.sortOrder || 0),
        status: form.status,
    };
}

function buildTierPayload(form) {
    return {
        display_avatar_frame_resource_id: Number(form.displayAvatarFrameResourceId || 0),
        display_badge_resource_id: Number(form.displayBadgeResourceId || 0),
        display_config_json: normalizedJson(form.displayConfigJson),
        max_level: Number(form.maxLevel),
        min_level: Number(form.minLevel),
        name: String(form.name || "").trim(),
        reward_resource_group_id: Number(form.rewardResourceGroupId || 0),
        status: form.status,
        track: form.track,
    };
}

function buildTrackPayload(form) {
    return {
        display_config_json: normalizedJson(form.displayConfigJson),
        name: String(form.name || "").trim(),
        sort_order: Number(form.sortOrder || 0),
        status: form.status,
    };
}

function nextRuleLevel(levelTrack) {
    const levels = (levelTrack?.rules || []).map((rule) => Number(rule.level || 0));
    return levels.length > 0 ? Math.max(...levels) + 1 : 0;
}

function nextTierStart(levelTrack) {
    const levels = (levelTrack?.tiers || []).map((tier) => Number(tier.maxLevel || 0));
    return levels.length > 0 ? Math.max(...levels) + 1 : 0;
}

function optionalId(value) {
    return value ? String(value) : "";
}

function valueOrEmpty(value) {
    return value === 0 || value ? String(value) : "";
}

function valueOrDefault(value, fallback) {
    return value === 0 || value ? String(value) : String(fallback);
}

function normalizedJson(value) {
    const raw = String(value || "").trim();
    return raw || "{}";
}

function sameForm(left, right) {
    return JSON.stringify(left || {}) === JSON.stringify(right || {});
}
