import { act, renderHook, waitFor } from "@testing-library/react";
import { afterEach, beforeEach, expect, test, vi } from "vitest";
import { useGiftListPage } from "./useResourcePages.js";

const mocks = vi.hoisted(() => ({
    batchCreateGifts: vi.fn(),
    can: vi.fn(),
    createGift: vi.fn(),
    listGifts: vi.fn(),
    listGiftTypes: vi.fn(),
    listResources: vi.fn(),
    reload: vi.fn(),
    showToast: vi.fn(),
    usePaginatedQuery: vi.fn(),
}));

vi.mock("@/app/auth/AuthProvider.jsx", () => ({
    useAuth: () => ({ can: mocks.can }),
}));

vi.mock("@/shared/hooks/usePaginatedQuery.js", () => ({
    usePaginatedQuery: mocks.usePaginatedQuery,
}));

vi.mock("@/shared/hooks/useRegionOptions.js", () => ({
    useRegionOptions: () => ({ loadingRegions: false, regionOptions: [{ label: "全球", value: "0" }] }),
}));

vi.mock("@/shared/ui/ConfirmProvider.jsx", () => ({
    useConfirm: () => vi.fn(),
}));

vi.mock("@/shared/ui/ToastProvider.jsx", () => ({
    useToast: () => ({ showToast: mocks.showToast }),
}));

vi.mock("@/features/resources/api", async (importOriginal) => ({
    ...(await importOriginal()),
    batchCreateGifts: mocks.batchCreateGifts,
    createGift: mocks.createGift,
    listGifts: mocks.listGifts,
    listGiftTypes: mocks.listGiftTypes,
    listResources: mocks.listResources,
}));

beforeEach(() => {
    mocks.can.mockReturnValue(true);
    mocks.batchCreateGifts.mockResolvedValue([]);
    mocks.createGift.mockResolvedValue({});
    mocks.listGifts.mockResolvedValue({ items: [], page: 1, pageSize: 100, total: 0 });
    mocks.listGiftTypes.mockResolvedValue([]);
    mocks.listResources.mockResolvedValue({ items: [], page: 1, pageSize: 100, total: 0 });
    mocks.reload.mockResolvedValue(undefined);
    mocks.usePaginatedQuery.mockReturnValue({
        data: { items: [], page: 1, pageSize: 50, total: 0 },
        error: null,
        loading: false,
        reload: mocks.reload,
    });
});

afterEach(() => {
    vi.clearAllMocks();
});

test("creating multiple gift drafts calls the batch create endpoint once", async () => {
    const { result } = renderHook(() => useGiftListPage());

    await act(async () => {
        result.current.openCreateGift();
    });
    await waitFor(() => expect(result.current.activeAction).toBe("create"));

    await act(async () => {
        result.current.setForm({
            ...giftDraft({ giftId: "rose", name: "Rose", resourceId: "11" }),
            items: [
                giftDraft({ giftId: "rose", name: "Rose", resourceId: "11" }),
                giftDraft({ giftId: "ring", name: "Ring", resourceId: "12" }),
            ],
            resourceId: "11",
        });
    });

    await act(async () => {
        await result.current.submitGift({ preventDefault: vi.fn() });
    });

    expect(mocks.batchCreateGifts).toHaveBeenCalledTimes(1);
    expect(mocks.batchCreateGifts).toHaveBeenCalledWith([
        expect.objectContaining({ giftId: "rose", name: "Rose", resourceId: 11 }),
        expect.objectContaining({ giftId: "ring", name: "Ring", resourceId: 12 }),
    ]);
    expect(mocks.createGift).not.toHaveBeenCalled();
    expect(mocks.reload).toHaveBeenCalledTimes(1);
});

function giftDraft(patch = {}) {
    return {
        chargeAssetType: "COIN",
        coinPrice: "10",
        cpRelationType: "",
        effectTypes: ["animation"],
        effectiveFrom: "",
        effectiveTo: "",
        enabled: true,
        giftId: "gift",
        giftTypeCode: "normal",
        name: "Gift",
        presentationJson: "{}",
        priceVersion: "default",
        regionIds: ["0"],
        resourceId: "1",
        sortOrder: "0",
        ...patch,
    };
}
