import { afterEach, expect, test, vi } from "vitest";
import { setAccessToken, setSelectedAppCode } from "@/shared/api/request";
import { getVipConfig, getVipProgram, grantVipTrialCard, updateVipConfig, updateVipProgram } from "./api";

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

test("vip program and level APIs normalize snake case responses", async () => {
    setSelectedAppCode("fami");
    vi.stubGlobal(
        "fetch",
        vi
            .fn()
            .mockResolvedValueOnce(
                envelope({
                    config: {
                        app_code: "fami",
                        config_version: 3,
                        grant_mode: "trial_card",
                        level_count: 9,
                        program_type: "tiered_privilege_v1",
                        status: "active",
                        trial_card_enabled: true,
                        upgrade_expiry_policy: "replace_from_now",
                    },
                    benefits: [
                        {
                            auto_equip: false,
                            benefit_code: "anti_kick",
                            benefit_type: "function",
                            execution_scope: "room",
                            metadata_json: "{}",
                            name: "防踢",
                            resource_id: 0,
                            resource_type: "",
                            sort_order: 320,
                            status: "active",
                            trial_enabled: true,
                            unlock_level: 9,
                        },
                    ],
                }),
            )
            .mockResolvedValueOnce(
                envelope({
                    levels: [
                        {
                            benefits: [
                                {
                                    benefit_code: "anti_kick",
                                    benefit_type: "function",
                                    unlock_level: 9,
                                    name: "防踢",
                                    resource_id: 0,
                                    resource_type: "",
                                    execution_scope: "room",
                                    auto_equip: false,
                                    metadata_json: "{}",
                                    sort_order: 10,
                                    status: "active",
                                    trial_enabled: true,
                                },
                                {
                                    auto_equip: false,
                                    benefit_code: "daily_coin_rebate",
                                    benefit_type: "function",
                                    execution_scope: "wallet",
                                    metadata_json: "{}",
                                    name: "金币返现",
                                    resource_id: 0,
                                    resource_type: "",
                                    sort_order: 20,
                                    status: "active",
                                    trial_enabled: true,
                                    unlock_level: 6,
                                },
                            ],
                            duration_ms: 2592000000,
                            level: 9,
                            name: "VIP9",
                            price_coin: 9000,
                            reward_resource_group_id: 99,
                            sort_order: 90,
                            status: "active",
                        },
                    ],
                    server_time_ms: 1780000000000,
                }),
            ),
    );

    const program = await getVipProgram();
    const config = await getVipConfig();

    expect(program).toMatchObject({
        appCode: "fami",
        benefitInheritancePolicy: "target_only",
        configVersion: 3,
        grantMode: "trial_card",
        levelCount: 9,
        programType: "tiered_privilege_v1",
        trialCardEnabled: true,
        upgradeExpiryPolicy: "replace_from_now",
    });
    expect(program.benefits).toEqual([
        expect.objectContaining({ benefitCode: "anti_kick", executionScope: "room", unlockLevel: 9 }),
    ]);
    expect(config.levels[0]).toMatchObject({
        durationMs: 2592000000,
        level: 9,
        priceCoin: 9000,
        rewardResourceGroupId: 99,
    });
    expect(config.levels[0].benefits[0]).toEqual({
        benefitCode: "anti_kick",
        benefitType: "function",
        unlockLevel: 9,
        name: "防踢",
        resourceId: 0,
        resourceType: "",
        executionScope: "room",
        autoEquip: false,
        metadataJson: "{}",
        sortOrder: 10,
        status: "active",
        trialEnabled: true,
    });
    expect(config.levels[0].benefits[1]).toMatchObject({
        benefitCode: "daily_coin_rebate",
        trialEnabled: false,
    });
    expect(requestHeaders(vi.mocked(fetch).mock.calls[0][1])["X-App-Code"]).toBe("fami");
});

test("vip updates and trial grant use generated contract paths", async () => {
    setSelectedAppCode("fami");
    vi.stubGlobal(
        "fetch",
        vi
            .fn()
            .mockResolvedValueOnce(
                envelope({ appCode: "fami", levelCount: 9, programType: "tiered_privilege_v1", status: "active" }),
            )
            .mockResolvedValueOnce(envelope({ levels: [] }))
            .mockResolvedValueOnce(envelope({ transactionId: "trial_1" }, 201)),
    );

    await updateVipProgram({
        benefitInheritancePolicy: "target_only",
        downgradePurchasePolicy: "reject",
        grantMode: "trial_card",
        levelCount: 9,
        programType: "tiered_privilege_v1",
        sameLevelExpiryPolicy: "extend_remaining",
        status: "active",
        trialCardEnabled: true,
        upgradeExpiryPolicy: "replace_from_now",
    });
    await updateVipConfig({
        levels: [
            {
                benefits: [
                    {
                        benefitCode: "room_entry_notice",
                        benefitType: "function",
                        unlockLevel: 2,
                        name: "VIP进房通知",
                        resourceId: 0,
                        resourceType: "",
                        executionScope: "room",
                        autoEquip: false,
                        metadataJson: "{}",
                        sortOrder: 10,
                        status: "active",
                        trialEnabled: true,
                    },
                    {
                        benefitCode: "daily_coin_rebate",
                        benefitType: "function",
                        unlockLevel: 6,
                        name: "金币返现",
                        resourceId: 0,
                        resourceType: "",
                        executionScope: "wallet",
                        autoEquip: false,
                        metadataJson: "{}",
                        sortOrder: 20,
                        status: "active",
                        trialEnabled: true,
                    },
                ],
                durationMs: 2592000000,
                level: 2,
                name: "VIP2",
                priceCoin: 2000,
                requiredRechargeCoinAmount: 0,
                rewardResourceGroupId: 22,
                sortOrder: 20,
                status: "active",
            },
        ],
    });
    await grantVipTrialCard({
        commandId: "vip-trial-card-grant-test",
        durationMs: 20 * 24 * 60 * 60 * 1000,
        level: 5,
        reason: "manual",
        targetUserId: "318705991371722752",
    });

    const [programUrl, programInit] = vi.mocked(fetch).mock.calls[0];
    const [configUrl, configInit] = vi.mocked(fetch).mock.calls[1];
    const [grantUrl, grantInit] = vi.mocked(fetch).mock.calls[2];
    expect(String(programUrl)).toContain("/api/v1/admin/activity/vip-program");
    expect(programInit?.method).toBe("PUT");
    expect(requestBody(programInit)).toMatchObject({
        config: {
            levelCount: 9,
            programType: "tiered_privilege_v1",
            status: "active",
            grantMode: "trial_card",
            benefitInheritancePolicy: "target_only",
            upgradeExpiryPolicy: "replace_from_now",
        },
    });
    expect(String(configUrl)).toContain("/api/v1/admin/activity/vip-levels");
    expect(configInit?.method).toBe("PUT");
    expect(requestBody(configInit)).toMatchObject({
        levels: [
            expect.objectContaining({
                benefits: [
                    expect.objectContaining({ benefitCode: "room_entry_notice" }),
                    expect.objectContaining({ benefitCode: "daily_coin_rebate", trialEnabled: false }),
                ],
            }),
        ],
    });
    expect(String(grantUrl)).toContain("/api/v1/admin/activity/vip-trial-card-grants");
    expect(grantInit?.method).toBe("POST");
    expect(requestBody(grantInit)).toMatchObject({ durationMs: 1728000000, level: 5 });
    expect(requestBody(grantInit)).not.toHaveProperty("resourceId");
});

function envelope(data: unknown, status = 200) {
    return new Response(JSON.stringify({ code: 0, data }), { status });
}

function requestHeaders(init: RequestInit | undefined): Record<string, string> {
    return (init?.headers || {}) as Record<string, string>;
}

function requestBody(init: RequestInit | undefined): Record<string, unknown> {
    return JSON.parse(String(init?.body || "{}")) as Record<string, unknown>;
}
