import { afterEach, expect, test, vi } from "vitest";
import { setAccessToken } from "@/shared/api/request";
import {
    batchCreateGifts,
    batchDeleteResources,
    createEmojiPack,
    createGift,
    createResource,
    createResourceGroup,
    disableResourceShopItem,
    disableGift,
    disableResource,
    disableResourceGroup,
    deleteGift,
    deleteResource,
    enableResourceShopItem,
    enableGift,
    enableResource,
    enableResourceGroup,
    getResourceIdentityAutoGrantConfig,
    grantResource,
    grantResourceGroup,
    listEmojiPackCategories,
    listEmojiPacks,
    listGiftTypes,
    listResourceGrants,
    listGifts,
    listResourceShopItems,
    listResourceShopPurchaseOrders,
    listResources,
    lookupResourceGrantTarget,
    revokeResourceGrant,
    updateGift,
    updateGiftTypes,
    updateResource,
    updateResourceIdentityAutoGrantConfig,
    updateResourceMp4Layouts,
    updateResourceGroup,
    upsertResourceShopItems,
} from "./api";

afterEach(() => {
    setAccessToken("");
    vi.unstubAllGlobals();
});

test("resource APIs use generated admin paths", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 10, total: 0 } })),
        ),
    );

    await listResources({ page: 1, page_size: 10, resource_type: "gift", status: "active" });
    await createResource({
        amount: 0,
        assetUrl: "https://media.haiyihy.com/resource/material.png",
        badgeForm: "strip",
        badgeKind: "level",
        coinPrice: 10,
        levelTrack: "wealth",
        managerGrantEnabled: true,
        metadataJson: '{"profile_card_layout":{"content_top":117,"content_height":1550}}',
        name: "VIP Badge",
        previewUrl: "https://media.haiyihy.com/resource/cover.png",
        priceType: "coin",
        resourceCode: "badge_vip_test",
        resourceType: "badge",
        sortOrder: 0,
        status: "active",
    });
    await updateResource(11, {
        amount: 0,
        assetUrl: "https://media.haiyihy.com/resource/material-updated.png",
        badgeForm: "tile",
        badgeKind: "normal",
        coinPrice: 20,
        managerGrantEnabled: false,
        metadataJson: '{"profile_card_layout":{"content_top":120,"content_height":1500}}',
        name: "VIP Badge Updated",
        previewUrl: "https://media.haiyihy.com/resource/cover-updated.png",
        priceType: "coin",
        resourceCode: "badge_vip_test",
        resourceType: "badge",
        sortOrder: 0,
        status: "active",
    });
    await deleteResource(11);
    await batchDeleteResources([11, 12]);
    await listGifts({ page: 1, page_size: 10, region_id: 1001 });
    await createGift({
        chargeAssetType: "COIN",
        coinPrice: 10,
        cpRelationType: "",
        effectiveAtMs: 1777766400000,
        effectiveFromMs: 0,
        effectiveToMs: 0,
        effectTypes: ["animation"],
        giftId: "rose",
        giftTypeCode: "normal",
        name: "Rose",
        presentationJson: "{}",
        priceVersion: "default",
        regionIds: [0],
        resourceId: 11,
        sortOrder: 0,
        status: "active",
    });
    await batchCreateGifts([
        {
            chargeAssetType: "COIN",
            coinPrice: 20,
            cpRelationType: "",
            effectiveAtMs: 1777766400000,
            effectiveFromMs: 0,
            effectiveToMs: 0,
            effectTypes: ["animation"],
            giftId: "ring",
            giftTypeCode: "normal",
            name: "Ring",
            presentationJson: "{}",
            priceVersion: "default",
            regionIds: [0],
            resourceId: 12,
            sortOrder: 1,
            status: "active",
        },
    ]);
    await enableResource(11);
    await disableResource(11);
    await createResourceGroup({
        description: "",
        groupCode: "starter_pack_test",
        items: [
            {
                durationDays: 7,
                itemType: "resource",
                resourceId: 11,
                sortOrder: 0,
            },
            {
                amount: 1000,
                assetType: "COIN",
                itemType: "wallet_asset",
                sortOrder: 1,
            },
        ],
        name: "Starter Pack",
        sortOrder: 0,
        status: "active",
    });
    await updateResourceGroup(22, {
        description: "updated",
        groupCode: "starter_pack_test",
        items: [],
        name: "Starter Pack Updated",
        sortOrder: 1,
        status: "disabled",
    });
    await enableResourceGroup(22);
    await disableResourceGroup(22);
    await updateGift("rose", {
        chargeAssetType: "COIN",
        coinPrice: 10,
        cpRelationType: "",
        effectiveAtMs: 1777766400000,
        effectiveFromMs: 0,
        effectiveToMs: 0,
        effectTypes: ["animation"],
        giftId: "rose",
        giftTypeCode: "normal",
        name: "Rose",
        presentationJson: "{}",
        priceVersion: "default",
        regionIds: [0],
        resourceId: 11,
        sortOrder: 0,
        status: "active",
    });
    await enableGift("rose");
    await disableGift("rose");
    await deleteGift("rose");
    await listResourceGrants({ page: 1, page_size: 10, target_user_id: 1001, status: "succeeded" });
    await lookupResourceGrantTarget("163000");
    await grantResource({
        commandId: "resource-grant-test",
        durationMs: 0,
        quantity: 1,
        reason: "manual",
        resourceId: 11,
        targetUserId: "318705991371722752",
    });
    await grantResourceGroup({
        commandId: "resource-group-grant-test",
        groupId: 22,
        reason: "manual",
        targetUserId: "1001",
    });
    await revokeResourceGrant("rgr_test");

    const [listUrl, listInit] = vi.mocked(fetch).mock.calls[0];
    const [createUrl, createInit] = vi.mocked(fetch).mock.calls[1];
    const [updateUrl, updateInit] = vi.mocked(fetch).mock.calls[2];
    const [deleteResourceUrl, deleteResourceInit] = vi.mocked(fetch).mock.calls[3];
    const [batchDeleteResourceUrl, batchDeleteResourceInit] = vi.mocked(fetch).mock.calls[4];
    const [giftListUrl, giftListInit] = vi.mocked(fetch).mock.calls[5];
    const [createGiftUrl, createGiftInit] = vi.mocked(fetch).mock.calls[6];
    const [batchCreateGiftUrl, batchCreateGiftInit] = vi.mocked(fetch).mock.calls[7];
    const [enableUrl, enableInit] = vi.mocked(fetch).mock.calls[8];
    const [disableUrl, disableInit] = vi.mocked(fetch).mock.calls[9];
    const [createGroupUrl, createGroupInit] = vi.mocked(fetch).mock.calls[10];
    const [updateGroupUrl, updateGroupInit] = vi.mocked(fetch).mock.calls[11];
    const [enableGroupUrl, enableGroupInit] = vi.mocked(fetch).mock.calls[12];
    const [disableGroupUrl, disableGroupInit] = vi.mocked(fetch).mock.calls[13];
    const [updateGiftUrl, updateGiftInit] = vi.mocked(fetch).mock.calls[14];
    const [enableGiftUrl, enableGiftInit] = vi.mocked(fetch).mock.calls[15];
    const [disableGiftUrl, disableGiftInit] = vi.mocked(fetch).mock.calls[16];
    const [deleteGiftUrl, deleteGiftInit] = vi.mocked(fetch).mock.calls[17];
    const [grantListUrl, grantListInit] = vi.mocked(fetch).mock.calls[18];
    const [grantTargetUrl, grantTargetInit] = vi.mocked(fetch).mock.calls[19];
    const [grantResourceUrl, grantResourceInit] = vi.mocked(fetch).mock.calls[20];
    const [grantGroupUrl, grantGroupInit] = vi.mocked(fetch).mock.calls[21];
    const [revokeGrantUrl, revokeGrantInit] = vi.mocked(fetch).mock.calls[22];

    expect(String(listUrl)).toContain("/api/v1/admin/resources?");
    expect(String(listUrl)).toContain("resource_type=gift");
    expect(String(listUrl)).toContain("status=active");
    expect(listInit?.method).toBe("GET");
    expect(String(createUrl)).toContain("/api/v1/admin/resources");
    expect(createInit?.method).toBe("POST");
    expect(JSON.parse(String(createInit?.body))).toMatchObject({
        badgeForm: "strip",
        badgeKind: "level",
        levelTrack: "wealth",
        metadataJson: '{"profile_card_layout":{"content_top":117,"content_height":1550}}',
        resourceCode: "badge_vip_test",
        resourceType: "badge",
        status: "active",
    });
    expect(String(updateUrl)).toContain("/api/v1/admin/resources/11");
    expect(updateInit?.method).toBe("PUT");
    expect(JSON.parse(String(updateInit?.body))).toMatchObject({
        badgeForm: "tile",
        badgeKind: "normal",
        metadataJson: '{"profile_card_layout":{"content_top":120,"content_height":1500}}',
    });
    expect(String(deleteResourceUrl)).toContain("/api/v1/admin/resources/11");
    expect(deleteResourceInit?.method).toBe("DELETE");
    expect(String(batchDeleteResourceUrl)).toContain("/api/v1/admin/resources/batch-delete");
    expect(batchDeleteResourceInit?.method).toBe("POST");
    expect(JSON.parse(String(batchDeleteResourceInit?.body))).toEqual({ resourceIds: [11, 12] });
    expect(String(giftListUrl)).toContain("/api/v1/admin/gifts?");
    expect(String(giftListUrl)).toContain("region_id=1001");
    expect(giftListInit?.method).toBe("GET");
    expect(String(createGiftUrl)).toContain("/api/v1/admin/gifts");
    expect(createGiftInit?.method).toBe("POST");
    expect(JSON.parse(String(createGiftInit?.body))).toMatchObject({ giftId: "rose", resourceId: 11 });
    expect(String(batchCreateGiftUrl)).toContain("/api/v1/admin/gifts/batch");
    expect(batchCreateGiftInit?.method).toBe("POST");
    expect(JSON.parse(String(batchCreateGiftInit?.body))).toMatchObject({ items: [{ giftId: "ring", resourceId: 12 }] });
    expect(String(enableUrl)).toContain("/api/v1/admin/resources/11/enable");
    expect(enableInit?.method).toBe("POST");
    expect(String(disableUrl)).toContain("/api/v1/admin/resources/11/disable");
    expect(disableInit?.method).toBe("POST");
    expect(String(createGroupUrl)).toContain("/api/v1/admin/resource-groups");
    expect(createGroupInit?.method).toBe("POST");
    expect(JSON.parse(String(createGroupInit?.body))).toMatchObject({
        groupCode: "starter_pack_test",
        items: [
            { durationDays: 7, itemType: "resource" },
            { amount: 1000, assetType: "COIN" },
        ],
    });
    expect(String(updateGroupUrl)).toContain("/api/v1/admin/resource-groups/22");
    expect(updateGroupInit?.method).toBe("PUT");
    expect(String(enableGroupUrl)).toContain("/api/v1/admin/resource-groups/22/enable");
    expect(enableGroupInit?.method).toBe("POST");
    expect(String(disableGroupUrl)).toContain("/api/v1/admin/resource-groups/22/disable");
    expect(disableGroupInit?.method).toBe("POST");
    expect(String(updateGiftUrl)).toContain("/api/v1/admin/gifts/rose");
    expect(updateGiftInit?.method).toBe("PUT");
    expect(String(enableGiftUrl)).toContain("/api/v1/admin/gifts/rose/enable");
    expect(enableGiftInit?.method).toBe("POST");
    expect(String(disableGiftUrl)).toContain("/api/v1/admin/gifts/rose/disable");
    expect(disableGiftInit?.method).toBe("POST");
    expect(String(deleteGiftUrl)).toContain("/api/v1/admin/gifts/rose");
    expect(deleteGiftInit?.method).toBe("DELETE");
    expect(String(grantListUrl)).toContain("/api/v1/admin/resource-grants?");
    expect(String(grantListUrl)).toContain("target_user_id=1001");
    expect(grantListInit?.method).toBe("GET");
    expect(String(grantTargetUrl)).toContain("/api/v1/admin/resource-grants/target?");
    expect(String(grantTargetUrl)).toContain("user_id=163000");
    expect(grantTargetInit?.method).toBe("GET");
    expect(String(grantResourceUrl)).toContain("/api/v1/admin/resource-grants/resource");
    expect(grantResourceInit?.method).toBe("POST");
    expect(JSON.parse(String(grantResourceInit?.body))).toMatchObject({
        resourceId: 11,
        targetUserId: "318705991371722752",
    });
    expect(String(grantGroupUrl)).toContain("/api/v1/admin/resource-grants/group");
    expect(grantGroupInit?.method).toBe("POST");
    expect(JSON.parse(String(grantGroupInit?.body))).toMatchObject({ groupId: 22, targetUserId: "1001" });
    expect(String(revokeGrantUrl)).toContain("/api/v1/admin/resource-grants/rgr_test/revoke");
    expect(revokeGrantInit?.method).toBe("POST");
});

test("resource identity auto grant config APIs use generated admin paths", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () =>
                new Response(
                    JSON.stringify({
                        code: 0,
                        data: {
                            items: [
                                { identity_type: "host", resource_group_id: 11 },
                                { identityType: "bd", resourceGroupId: 12 },
                            ],
                        },
                    }),
                ),
        ),
    );

    const config = await getResourceIdentityAutoGrantConfig();
    await updateResourceIdentityAutoGrantConfig({
        items: [
            { identity_type: "host", resource_group_id: 11 },
            { identity_type: "bd", resource_group_id: 12 },
            { identity_type: "bd_leader", resource_group_id: 13 },
            { identity_type: "agency", resource_group_id: 14 },
            { identity_type: "manager", resource_group_id: 0 },
        ],
    });

    const [getUrl, getInit] = vi.mocked(fetch).mock.calls[0];
    const [putUrl, putInit] = vi.mocked(fetch).mock.calls[1];

    expect(config.items).toMatchObject([
        { identityType: "host", resourceGroupId: 11 },
        { identityType: "bd", resourceGroupId: 12 },
    ]);
    expect(String(getUrl)).toContain("/api/v1/admin/resource-groups/identity-auto-grant-config");
    expect(getInit?.method).toBe("GET");
    expect(String(putUrl)).toContain("/api/v1/admin/resource-groups/identity-auto-grant-config");
    expect(putInit?.method).toBe("PUT");
    expect(JSON.parse(String(putInit?.body))).toEqual({
        items: [
            { identity_type: "host", resource_group_id: 11 },
            { identity_type: "bd", resource_group_id: 12 },
            { identity_type: "bd_leader", resource_group_id: 13 },
            { identity_type: "agency", resource_group_id: 14 },
            { identity_type: "manager", resource_group_id: 0 },
        ],
    });
});

test("resource mp4 layout batch API uses narrow update endpoint", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(async () => new Response(JSON.stringify({ code: 0, data: [] }))),
    );

    await updateResourceMp4Layouts([
        {
            metadataJson:
                '{"animation_format":"mp4","mp4_alpha_layout":{"alpha_layout":"normal","video_w":750,"video_h":1334,"rgb_frame":[0,0,750,1334],"alpha_frame":null,"confirmed":true,"detect_version":1}}',
            resourceId: 11,
        },
    ]);

    const [url, init] = vi.mocked(fetch).mock.calls[0];
    expect(String(url)).toContain("/api/v1/admin/resources/mp4-layouts/batch");
    expect(init?.method).toBe("PUT");
    expect(JSON.parse(String(init?.body))).toMatchObject({
        items: [{ resourceId: 11 }],
    });
});

test("emoji pack APIs use generated admin paths", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(async () => new Response(JSON.stringify({ code: 0, data: [] }))),
    );

    await listEmojiPackCategories();
    await listEmojiPacks({ page: 1, page_size: 10, status: "active" });
    await createEmojiPack({
        animationUrl: "https://media.haiyihy.com/emoji/wave.svga",
        category: "热门",
        coverUrl: "https://media.haiyihy.com/emoji/wave.png",
        name: "Wave",
        pricingType: "paid",
        regionIds: [0],
        sortOrder: 0,
    });

    const [categoryUrl, categoryInit] = vi.mocked(fetch).mock.calls[0];
    const [listUrl, listInit] = vi.mocked(fetch).mock.calls[1];
    const [createUrl, createInit] = vi.mocked(fetch).mock.calls[2];

    expect(String(categoryUrl)).toContain("/api/v1/admin/emoji-packs/categories");
    expect(categoryInit?.method).toBe("GET");
    expect(String(listUrl)).toContain("/api/v1/admin/emoji-packs?");
    expect(String(listUrl)).toContain("status=active");
    expect(listInit?.method).toBe("GET");
    expect(String(createUrl)).toContain("/api/v1/admin/emoji-packs");
    expect(createInit?.method).toBe("POST");
    expect(JSON.parse(String(createInit?.body))).toMatchObject({
        category: "热门",
        name: "Wave",
        pricingType: "paid",
    });
});

test("resource shop APIs use generated admin paths", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 10, total: 0 } })),
        ),
    );

    await listResourceShopPurchaseOrders({
        page: 1,
        page_size: 10,
        resource_type: "avatar_frame",
        user_keyword: "163000",
    });
    await listResourceShopItems({ page: 1, page_size: 10, resource_type: "avatar_frame", status: "active" });
    await upsertResourceShopItems({
        items: [
            {
                coinPrice: 120,
                durationDays: 3,
                effectiveFromMs: 0,
                effectiveToMs: 0,
                resourceId: 11,
                sortOrder: 0,
                status: "active",
            },
        ],
    });
    await enableResourceShopItem(99);
    await disableResourceShopItem(99);

    const [purchaseUrl, purchaseInit] = vi.mocked(fetch).mock.calls[0];
    const [listUrl, listInit] = vi.mocked(fetch).mock.calls[1];
    const [upsertUrl, upsertInit] = vi.mocked(fetch).mock.calls[2];
    const [enableUrl, enableInit] = vi.mocked(fetch).mock.calls[3];
    const [disableUrl, disableInit] = vi.mocked(fetch).mock.calls[4];

    expect(String(purchaseUrl)).toContain("/api/v1/admin/resource-shop/purchase-orders?");
    expect(String(purchaseUrl)).toContain("resource_type=avatar_frame");
    expect(String(purchaseUrl)).toContain("user_keyword=163000");
    expect(purchaseInit?.method).toBe("GET");
    expect(String(listUrl)).toContain("/api/v1/admin/resource-shop/items?");
    expect(String(listUrl)).toContain("resource_type=avatar_frame");
    expect(String(listUrl)).toContain("status=active");
    expect(listInit?.method).toBe("GET");
    expect(String(upsertUrl)).toContain("/api/v1/admin/resource-shop/items");
    expect(upsertInit?.method).toBe("POST");
    expect(JSON.parse(String(upsertInit?.body))).toMatchObject({
        items: [{ coinPrice: 120, durationDays: 3, resourceId: 11, status: "active" }],
    });
    expect(String(enableUrl)).toContain("/api/v1/admin/resource-shop/items/99/enable");
    expect(enableInit?.method).toBe("POST");
    expect(String(disableUrl)).toContain("/api/v1/admin/resource-shop/items/99/disable");
    expect(disableInit?.method).toBe("POST");
});

test("gift type APIs save all tabs with one request", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(async () => new Response(JSON.stringify({ code: 0, data: [] }))),
    );

    await listGiftTypes();
    await updateGiftTypes({
        items: [
            {
                displayName: "普通礼物",
                sortOrder: 10,
                status: "active",
                tabKey: "normal",
                tabName: "Gift",
            },
            {
                displayName: "幸运礼物",
                sortOrder: 30,
                status: "active",
                tabKey: "lucky",
                tabName: "Lucky",
            },
        ],
    });

    const [listUrl, listInit] = vi.mocked(fetch).mock.calls[0];
    const [updateUrl, updateInit] = vi.mocked(fetch).mock.calls[1];

    expect(String(listUrl)).toContain("/api/v1/admin/gift-types");
    expect(listInit?.method).toBe("GET");
    expect(String(updateUrl)).toContain("/api/v1/admin/gift-types");
    expect(String(updateUrl)).not.toContain("/api/v1/admin/gift-types/normal");
    expect(updateInit?.method).toBe("PUT");
    expect(JSON.parse(String(updateInit?.body))).toMatchObject({
        items: [
            {
                displayName: "普通礼物",
                tabKey: "normal",
                tabName: "Gift",
            },
            {
                displayName: "幸运礼物",
                tabKey: "lucky",
                tabName: "Lucky",
            },
        ],
    });
    expect(vi.mocked(fetch)).toHaveBeenCalledTimes(2);
});
