import { useCallback, useEffect, useMemo, useState } from "react";
import { parseForm } from "@/shared/forms/validation";
import { usePaginatedQuery } from "@/shared/hooks/usePaginatedQuery.js";
import { useToast } from "@/shared/ui/ToastProvider.jsx";
import { listResourceGroups, listResources } from "@/features/resources/api";
import {
    createAchievementDefinition,
    listAchievementDefinitions,
    updateAchievementDefinition,
} from "@/features/achievements/api";
import { useAchievementAbilities } from "@/features/achievements/permissions.js";
import { achievementFormSchema } from "@/features/achievements/schema";

const pageSize = 50;
const emptyData = { items: [], page: 1, pageSize, total: 0 };
const resourcePageQuery = { page: 1, page_size: 500, resource_type: "badge", status: "active" };
const groupPageQuery = { page: 1, page_size: 500, status: "active" };

const emptyCondition = (condition = {}) => ({
    dimensionFilterJson: condition.dimensionFilterJson || "{}",
    metricType: condition.metricType || "",
    targetUnit: condition.targetUnit || "count",
    targetValue: condition.targetValue === 0 || condition.targetValue ? String(condition.targetValue) : "",
});

const emptyForm = (achievement = {}) => ({
    achievementType: achievement.achievementType || "ordinary",
    autoPinPolicy: achievement.autoPinPolicy || "if_empty",
    collectionId: achievement.collectionId || "",
    collectionType: achievement.collectionType || "ordinary",
    conditions: achievement.conditions?.length ? achievement.conditions.map(emptyCondition) : [emptyCondition()],
    description: achievement.description || "",
    displayConfigJson: achievement.displayConfigJson || "{}",
    effectiveFrom: msToDatetimeLocal(achievement.effectiveFromMs),
    effectiveTo: msToDatetimeLocal(achievement.effectiveToMs),
    honorVisibility: achievement.honorVisibility ?? true,
    primaryBadgeResourceId: optionalId(achievement.primaryBadgeResourceId),
    rewardResourceGroupId: optionalId(achievement.rewardResourceGroupId),
    sortOrder: valueOrDefault(achievement.sortOrder, 0),
    status: achievement.status || "draft",
    title: achievement.title || "",
});

export function useAchievementsPage() {
    const abilities = useAchievementAbilities();
    const { showToast } = useToast();
    const [collectionType, setCollectionType] = useState("");
    const [collectionId, setCollectionId] = useState("");
    const [page, setPage] = useState(1);
    const [activeAction, setActiveAction] = useState("");
    const [selectedAchievement, setSelectedAchievement] = useState(null);
    const [form, setForm] = useState(() => emptyForm());
    const [loadingAction, setLoadingAction] = useState("");
    const [badgeResources, setBadgeResources] = useState([]);
    const [resourceGroups, setResourceGroups] = useState([]);

    const filters = useMemo(
        () => ({
            collection_id: collectionId,
            collection_type: collectionType,
        }),
        [collectionId, collectionType],
    );
    const {
        data = emptyData,
        error,
        loading,
        reload,
    } = usePaginatedQuery({
        errorMessage: "加载成就配置失败",
        fetcher: listAchievementDefinitions,
        filters,
        page,
        pageSize,
        queryKey: ["achievements", filters, page],
    });

    const loadOptions = useCallback(async () => {
        try {
            const [resourcePage, groupPage] = await Promise.all([
                listResources(resourcePageQuery),
                listResourceGroups(groupPageQuery),
            ]);
            setBadgeResources(resourcePage.items || []);
            setResourceGroups(groupPage.items || []);
        } catch (err) {
            showToast(err.message || "加载资源选项失败", "error");
        }
    }, [showToast]);

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

    const changeCollectionType = resetSetter(setCollectionType, setPage);
    const changeCollectionId = resetSetter(setCollectionId, setPage);

    const resetFilters = () => {
        setCollectionType("");
        setCollectionId("");
        setPage(1);
    };

    const openCreate = () => {
        setSelectedAchievement(null);
        setForm(emptyForm());
        setActiveAction("create");
    };

    const openEdit = (achievement) => {
        if (!achievement?.achievementId) {
            return;
        }
        setSelectedAchievement(achievement);
        setForm(emptyForm(achievement));
        setActiveAction("edit");
    };

    const closeAction = () => {
        setActiveAction("");
        setSelectedAchievement(null);
    };

    const reloadAll = async () => {
        await Promise.all([reload(), loadOptions()]);
    };

    const submitAchievement = async (event) => {
        event.preventDefault();
        const editing = activeAction === "edit";
        if (editing && !selectedAchievement?.achievementId) {
            return;
        }
        await runAction(editing ? "edit" : "create", editing ? "成就已更新" : "成就已创建", async () => {
            const payload = buildAchievementPayload(parseForm(achievementFormSchema, form));
            if (editing) {
                await updateAchievementDefinition(selectedAchievement.achievementId, payload);
            } else {
                await createAchievementDefinition(payload);
            }
            closeAction();
            setForm(emptyForm());
            await reload();
        });
    };

    const toggleAchievement = async (achievement, nextEnabled = achievement.status !== "active") => {
        if (!abilities.canUpdate || !achievement?.achievementId || achievement.status === "archived") {
            return;
        }
        const nextStatus = nextEnabled ? "active" : "paused";
        if (achievement.status === nextStatus) {
            return;
        }
        await runAction(`status-${achievement.achievementId}`, nextEnabled ? "成就已启用" : "成就已暂停", async () => {
            await updateAchievementDefinition(
                achievement.achievementId,
                buildAchievementPayload(emptyForm({ ...achievement, status: nextStatus })),
            );
            await reload();
        });
    };

    const addCondition = () => {
        setForm((current) => ({ ...current, conditions: [...current.conditions, emptyCondition()] }));
    };

    const removeCondition = (index) => {
        setForm((current) => ({
            ...current,
            conditions:
                current.conditions.length > 1
                    ? current.conditions.filter((_, itemIndex) => itemIndex !== index)
                    : current.conditions,
        }));
    };

    const updateCondition = (index, key, value) => {
        setForm((current) => ({
            ...current,
            conditions: current.conditions.map((condition, itemIndex) =>
                itemIndex === index ? { ...condition, [key]: value } : condition,
            ),
        }));
    };

    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,
        addCondition,
        badgeResources,
        changeCollectionId,
        changeCollectionType,
        closeAction,
        collectionId,
        collectionType,
        data,
        error,
        form,
        loading,
        loadingAction,
        openCreate,
        openEdit,
        page,
        reload: reloadAll,
        removeCondition,
        resetFilters,
        resourceGroups,
        selectedAchievement,
        setForm,
        setPage,
        submitAchievement,
        toggleAchievement,
        updateCondition,
    };
}

function buildAchievementPayload(form) {
    return {
        achievement_type: form.achievementType,
        auto_pin_policy: form.autoPinPolicy,
        collection_id: String(form.collectionId || "").trim(),
        collection_type: form.collectionType,
        conditions: form.conditions.map((condition) => ({
            dimension_filter_json: normalizedJson(condition.dimensionFilterJson),
            metric_type: String(condition.metricType || "").trim(),
            target_unit: String(condition.targetUnit || "").trim(),
            target_value: Number(condition.targetValue || 0),
        })),
        description: String(form.description || "").trim(),
        display_config_json: normalizedJson(form.displayConfigJson),
        effective_from_ms: datetimeLocalToMs(form.effectiveFrom),
        effective_to_ms: datetimeLocalToMs(form.effectiveTo),
        honor_visibility: Boolean(form.honorVisibility),
        primary_badge_resource_id: Number(form.primaryBadgeResourceId || 0),
        reward_resource_group_id: Number(form.rewardResourceGroupId || 0),
        sort_order: Number(form.sortOrder || 0),
        status: form.status,
        title: String(form.title || "").trim(),
    };
}

function resetSetter(setter, setPage) {
    return (value) => {
        setter(value);
        setPage(1);
    };
}

function msToDatetimeLocal(value) {
    if (!value) {
        return "";
    }
    const date = new Date(Number(value));
    if (Number.isNaN(date.getTime())) {
        return "";
    }
    const local = new Date(date.getTime() - date.getTimezoneOffset() * 60000);
    return local.toISOString().slice(0, 16);
}

function datetimeLocalToMs(value) {
    const trimmed = String(value || "").trim();
    if (!trimmed) {
        return 0;
    }
    const parsed = new Date(trimmed).getTime();
    return Number.isFinite(parsed) ? parsed : 0;
}

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

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

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