import { afterEach, expect, test, vi } from "vitest";
import { setAccessToken } from "@/shared/api/request";
import {
    createCoinAdjustment,
    exportCoinSellerLedger,
    getGiftDiamondRatios,
    getWheelConfig,
    getWheelDrawSummary,
    listCoinLedger,
    listCoinAdjustments,
    listCoinSellerLedger,
    listGiftRecords,
    listWheelDraws,
    lookupCoinAdjustmentTarget,
    updateGiftDiamondRatios,
    updateWheelConfig,
} from "./api";

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

test("gift diamond ratio APIs use operations paths", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(async () => new Response(JSON.stringify({ code: 0, data: { regionId: 1001, items: [] } }))),
    );

    await getGiftDiamondRatios(1001);
    await updateGiftDiamondRatios({
        regionId: 1001,
        ratios: { lucky: "40.00", normal: "30.00", super_lucky: "50.00" },
        returnCoinRatios: { lucky: "10.00", normal: "30.00", super_lucky: "1.00" },
    });

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

    expect(String(getUrl)).toContain("/api/v1/admin/operations/gift-diamond-ratios?");
    expect(String(getUrl)).toContain("region_id=1001");
    expect(getInit?.method).toBe("GET");
    expect(String(putUrl)).toContain("/api/v1/admin/operations/gift-diamond-ratios");
    expect(putInit?.method).toBe("PUT");
    expect(JSON.parse(String(putInit?.body))).toMatchObject({
        regionId: 1001,
        ratios: { lucky: "40.00", normal: "30.00", super_lucky: "50.00" },
        returnCoinRatios: { lucky: "10.00", normal: "30.00", super_lucky: "1.00" },
    });
});

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

    await listCoinAdjustments({ page: 1, page_size: 20, user_keyword: "1001" });
    await lookupCoinAdjustmentTarget("1001");
    await createCoinAdjustment({
        amount: 500,
        commandId: "coin-adjustment-test",
        reason: "运营发放",
        remark: "客服复核后补发",
        targetUserId: "1001",
    });

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

    expect(String(listUrl)).toContain("/api/v1/admin/operations/coin-adjustments?");
    expect(String(listUrl)).toContain("user_keyword=1001");
    expect(listInit?.method).toBe("GET");
    expect(String(lookupUrl)).toContain("/api/v1/admin/operations/coin-adjustments/target?");
    expect(String(lookupUrl)).toContain("user_id=1001");
    expect(lookupInit?.method).toBe("GET");
    expect(String(createUrl)).toContain("/api/v1/admin/operations/coin-adjustments");
    expect(createInit?.method).toBe("POST");
    expect(JSON.parse(String(createInit?.body))).toMatchObject({
        amount: 500,
        commandId: "coin-adjustment-test",
        reason: "运营发放",
        remark: "客服复核后补发",
        targetUserId: "1001",
    });
});

test("coin ledger API sends type filter", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 20, total: 0 } })),
        ),
    );

    await listCoinLedger({
        biz_type: "game_debit",
        page: 1,
        page_size: 20,
        user_keyword: "168359",
    });

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

    expect(String(listUrl)).toContain("/api/v1/admin/operations/coin-ledger?");
    expect(String(listUrl)).toContain("user_keyword=168359");
    expect(String(listUrl)).toContain("biz_type=game_debit");
    expect(listInit?.method).toBe("GET");
});

test("gift record API uses generated path with sender, scene and UTC range filters", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 30, total: 0 } })),
        ),
    );

    await listGiftRecords({
        end_at_ms: 2000,
        page: 1,
        page_size: 30,
        scene: "room",
        sender_display_user_id: "888888",
        sender_user_id: "1001",
        sender_username: "送礼人",
        start_at_ms: 1000,
    });

    const [listUrl, listInit] = vi.mocked(fetch).mock.calls[0];
    expect(String(listUrl)).toContain("/api/v1/admin/operations/gift-records?");
    expect(String(listUrl)).toContain("scene=room");
    expect(String(listUrl)).toContain("sender_display_user_id=888888");
    expect(String(listUrl)).toContain("sender_user_id=1001");
    expect(String(listUrl)).toContain("sender_username=%E9%80%81%E7%A4%BC%E4%BA%BA");
    expect(String(listUrl)).toContain("start_at_ms=1000");
    expect(String(listUrl)).toContain("end_at_ms=2000");
    expect(listInit?.method).toBe("GET");
});

test("coin seller ledger API uses generated admin path and filters", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(
            async () => new Response(JSON.stringify({ code: 0, data: { items: [], page: 1, pageSize: 20, total: 0 } })),
        ),
    );

    await listCoinSellerLedger({
        ledger_type: "sub_seller_transfer",
        page: 1,
        page_size: 20,
        seller_user_id: "3001",
    });

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

    expect(String(listUrl)).toContain("/api/v1/admin/operations/coin-seller-ledger?");
    expect(String(listUrl)).toContain("seller_user_id=3001");
    expect(String(listUrl)).toContain("ledger_type=sub_seller_transfer");
    expect(listInit?.method).toBe("GET");
});

test("coin seller ledger export API sends current filters without pagination", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn(async () => new Response("seller,amount\n", { status: 200 })),
    );

    await exportCoinSellerLedger({
        end_at_ms: "2000",
        ledger_type: "admin_stock_credit",
        seller_keyword: "HUNTER",
        start_at_ms: "1000",
    });

    const [exportUrl, exportInit] = vi.mocked(fetch).mock.calls[0];

    expect(String(exportUrl)).toContain("/api/v1/admin/operations/coin-seller-ledger/export?");
    expect(String(exportUrl)).toContain("seller_keyword=HUNTER");
    expect(String(exportUrl)).toContain("ledger_type=admin_stock_credit");
    expect(String(exportUrl)).toContain("start_at_ms=1000");
    expect(String(exportUrl)).toContain("end_at_ms=2000");
    expect(String(exportUrl)).not.toContain("page=");
    expect(exportInit?.method).toBe("GET");
});

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

    await getWheelConfig("default");
    await updateWheelConfig({
        draw_price_coins: 10000,
        effective_from_ms: 0,
        enabled: true,
        initial_pool_coins: 0,
        max_single_rtp_payout: 0,
        pool_rate_percent: 90,
        pool_reserve_coins: 0,
        settlement_window_draws: 1000,
        target_rtp_percent: 90,
        tiers: [
            {
                display_name: "金币",
                enabled: true,
                metadata_json: "{}",
                probability_percent: 70,
                reward_coins: 10000,
                reward_count: 1,
                reward_id: "",
                reward_type: "coin",
                rtp_value_coins: 10000,
                tier_id: "coin",
            },
            {
                display_name: "礼物",
                enabled: true,
                metadata_json: "{}",
                probability_percent: 20,
                reward_coins: 0,
                reward_count: 1,
                reward_id: "gift_1001",
                reward_type: "gift",
                rtp_value_coins: 5000,
                tier_id: "gift",
            },
            {
                display_name: "装扮",
                enabled: true,
                metadata_json: "{}",
                probability_percent: 10,
                reward_coins: 0,
                reward_count: 1,
                reward_id: "dress_1001",
                reward_type: "dress",
                rtp_value_coins: 0,
                tier_id: "dress",
            },
        ],
        wheel_id: "default",
    });
    await listWheelDraws({ page: 1, page_size: 20, status: "granted", user_id: "1001", wheel_id: "default" });
    await getWheelDrawSummary({ status: "granted", user_id: "1001", wheel_id: "default" });

    const [getUrl, getInit] = vi.mocked(fetch).mock.calls[0];
    const [putUrl, putInit] = vi.mocked(fetch).mock.calls[1];
    const [drawsUrl, drawsInit] = vi.mocked(fetch).mock.calls[2];
    const [summaryUrl, summaryInit] = vi.mocked(fetch).mock.calls[3];

    expect(String(getUrl)).toContain("/api/v1/admin/activity/wheel/config?");
    expect(String(getUrl)).toContain("wheel_id=default");
    expect(getInit?.method).toBe("GET");
    expect(String(putUrl)).toContain("/api/v1/admin/activity/wheel/config?");
    expect(putInit?.method).toBe("PUT");
    expect(JSON.parse(String(putInit?.body))).toMatchObject({ enabled: true, wheel_id: "default" });
    expect(String(drawsUrl)).toContain("/api/v1/admin/activity/wheel/draws?");
    expect(String(drawsUrl)).toContain("user_id=1001");
    expect(String(drawsUrl)).toContain("status=granted");
    expect(drawsInit?.method).toBe("GET");
    expect(String(summaryUrl)).toContain("/api/v1/admin/activity/wheel/draw-summary?");
    expect(summaryInit?.method).toBe("GET");
});
