import { afterEach, expect, test, vi } from "vitest";
import { setAccessToken } from "@/shared/api/request";
import { getAppUser, listAppUsers, listPrettyDisplayIDs, recyclePrettyDisplayID } from "./api";

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

test("listPrettyDisplayIDs uses admin endpoint and normalizes snake case fields", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () =>
                new Response(
                    JSON.stringify({
                        code: 0,
                        data: {
                            items: [
                                {
                                    assigned_user_id: "10001",
                                    display_user_id: "VIP2026",
                                    pool: {
                                        level_track: "wealth",
                                        max_level: 10,
                                        min_level: 1,
                                        name: "财富池",
                                        pool_id: "pool-1",
                                        rule_type: "aabbcc",
                                        status: "active",
                                    },
                                    pool_id: "pool-1",
                                    pretty_id: "pretty-1",
                                    source: "pool",
                                    status: "assigned",
                                },
                            ],
                            page: 1,
                            page_size: 20,
                            total: 1,
                        },
                    }),
                ),
        ),
    );

    const result = await listPrettyDisplayIDs({ keyword: "VIP", page: 1, page_size: 20, status: "assigned" });
    const [url, init] = vi.mocked(fetch).mock.calls[0];

    expect(String(url)).toContain("/api/v1/admin/users/pretty-ids?");
    expect(String(url)).toContain("keyword=VIP");
    expect(String(url)).toContain("status=assigned");
    expect(init?.method).toBe("GET");
    expect(result.pageSize).toBe(20);
    expect(result.items[0]).toMatchObject({
        assignedUserId: "10001",
        displayUserId: "VIP2026",
        pool: { levelTrack: "wealth", poolId: "pool-1" },
        prettyId: "pretty-1",
    });
});

test("listPrettyDisplayIDs normalizes assigned user and operator snapshots", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () =>
                new Response(
                    JSON.stringify({
                        code: 0,
                        data: {
                            items: [
                                {
                                    assigned_user: {
                                        avatar: "https://cdn.example/u.png",
                                        default_display_user_id: "10001",
                                        display_user_id: "777777",
                                        user_id: "9001",
                                        username: "pretty owner",
                                    },
                                    assigned_user_id: "9001",
                                    created_by_admin_id: "7",
                                    display_user_id: "777777",
                                    operator: {
                                        account: "ops",
                                        admin_id: "8",
                                        name: "运营",
                                        type: "admin",
                                    },
                                    pretty_id: "pretty-2",
                                    source: "admin_grant",
                                    status: "assigned",
                                    updated_by_admin_id: "8",
                                },
                            ],
                            page: 1,
                            page_size: 20,
                            total: 1,
                        },
                    }),
                ),
        ),
    );

    const result = await listPrettyDisplayIDs({ page: 1, page_size: 20 });

    expect(result.items[0]).toMatchObject({
        assignedUser: {
            avatar: "https://cdn.example/u.png",
            defaultDisplayUserId: "10001",
            displayUserId: "777777",
            userId: "9001",
            username: "pretty owner",
        },
        operator: {
            account: "ops",
            adminId: "8",
            name: "运营",
            type: "admin",
        },
        updatedByAdminId: "8",
    });
});

test("recyclePrettyDisplayID uses generated recycle endpoint", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () =>
                new Response(
                    JSON.stringify({
                        code: 0,
                        data: {
                            assigned_user_id: "",
                            display_user_id: "777777",
                            pretty_id: "pretty-2",
                            released_at_ms: 1782493200000,
                            source: "admin_grant",
                            status: "released",
                        },
                    }),
                ),
        ),
    );

    const result = await recyclePrettyDisplayID("pretty-2");
    const [url, init] = vi.mocked(fetch).mock.calls[0];

    expect(String(url)).toContain("/api/v1/admin/users/pretty-ids/pretty-2/recycle");
    expect(init?.method).toBe("POST");
    expect(result).toMatchObject({
        assignedUserId: "",
        displayUserId: "777777",
        prettyId: "pretty-2",
        status: "released",
    });
});

test("listPrettyDisplayIDs normalizes zero assigned user as empty", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () =>
                new Response(
                    JSON.stringify({
                        code: 0,
                        data: {
                            items: [
                                {
                                    assigned_user_id: "0",
                                    display_user_id: "00002",
                                    pretty_id: "pretty-0",
                                    source: "pool",
                                    status: "available",
                                },
                            ],
                            page: 1,
                            page_size: 20,
                            total: 1,
                        },
                    }),
                ),
        ),
    );

    const result = await listPrettyDisplayIDs({ page: 1, page_size: 20 });

    expect(result.items[0]).toMatchObject({
        assignedUser: undefined,
        assignedUserId: "",
        displayUserId: "00002",
    });
});

test("listAppUsers sends country region and time filters", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 50, total: 0 } })),
        ),
    );

    const result = await listAppUsers({
        country: "PH",
        end_ms: 2000,
        page: 1,
        page_size: 50,
        region_id: 3,
        start_ms: 1000,
    });
    const [url, init] = vi.mocked(fetch).mock.calls[0];

    expect(result.items).toEqual([]);
    expect(String(url)).toContain("/api/v1/app/users?");
    expect(String(url)).toContain("country=PH");
    expect(String(url)).toContain("region_id=3");
    expect(String(url)).toContain("start_ms=1000");
    expect(String(url)).toContain("end_ms=2000");
    expect(init?.method).toBe("GET");
});

test("listAppUsers normalizes pretty display id fields from snake case", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () =>
                new Response(
                    JSON.stringify({
                        code: 0,
                        data: {
                            items: [
                                {
                                    avatar: "https://cdn.example/avatar.png",
                                    coin: 99,
                                    default_display_user_id: "123456",
                                    display_user_id: "123456",
                                    pretty_display_user_id: "VIP2026",
                                    pretty_id: "pretty-2026",
                                    user_id: "10001",
                                    username: "tester",
                                    vip: {
                                        active: true,
                                        expires_at_ms: 1790000000000,
                                        level: 3,
                                        name: "黄金会员",
                                    },
                                },
                            ],
                            page: 1,
                            page_size: 50,
                            total: 1,
                        },
                    }),
                ),
        ),
    );

    const result = await listAppUsers({ page: 1, page_size: 50 });

    expect(result.pageSize).toBe(50);
    expect(result.items[0]).toMatchObject({
        defaultDisplayUserId: "123456",
        displayUserId: "123456",
        prettyDisplayUserId: "VIP2026",
        prettyId: "pretty-2026",
        userId: "10001",
        username: "tester",
        vip: expect.objectContaining({
            active: true,
            level: 3,
            name: "黄金会员",
        }),
    });
});

test("getAppUser uses detail endpoint and normalizes assets", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () =>
                new Response(
                    JSON.stringify({
                        code: 0,
                        data: {
                            display_user_id: "123456",
                            default_display_user_id: "123456",
                            pretty_display_user_id: "VIP888",
                            pretty_id: "pretty-888",
                            user_id: "10001",
                            balances: [
                                {
                                    asset_type: "COIN",
                                    available_amount: 1200,
                                    frozen_amount: 50,
                                    total_amount: 1250,
                                    version: 7,
                                },
                            ],
                            equipped_resources: [
                                {
                                    entitlement_id: "ent-1",
                                    equipped: true,
                                    name: "金色头像框",
                                    quantity: 1,
                                    remaining_quantity: 1,
                                    resource_code: "frame_gold",
                                    resource_id: 9,
                                    resource_type: "avatar_frame",
                                },
                            ],
                            resources: [
                                {
                                    entitlement_id: "ent-1",
                                    equipped: true,
                                    name: "金色头像框",
                                    quantity: 1,
                                    remaining_quantity: 1,
                                    resource_code: "frame_gold",
                                    resource_id: 9,
                                    resource_type: "avatar_frame",
                                },
                            ],
                        },
                    }),
                ),
        ),
    );

    const result = await getAppUser("10001");
    const [url, init] = vi.mocked(fetch).mock.calls[0];

    expect(String(url)).toContain("/api/v1/app/users/10001");
    expect(init?.method).toBe("GET");
    expect(result.defaultDisplayUserId).toBe("123456");
    expect(result.prettyDisplayUserId).toBe("VIP888");
    expect(result.prettyId).toBe("pretty-888");
    expect(result.balances?.[0]).toMatchObject({
        assetType: "COIN",
        availableAmount: 1200,
        frozenAmount: 50,
        totalAmount: 1250,
        version: 7,
    });
    expect(result.equippedResources?.[0]).toMatchObject({
        equipped: true,
        name: "金色头像框",
        resourceType: "avatar_frame",
    });
    expect(result.resources?.[0]).toMatchObject({
        entitlementId: "ent-1",
        resourceCode: "frame_gold",
    });
});
