import { afterEach, expect, test, vi } from "vitest";
import { setAccessToken, setSelectedAppCode } from "@/shared/api/request";
import {
    createExternalAdminUser,
    getExternalAdminUserPermissions,
    listExternalAdminUsers,
    listExternalAdminPermissionCatalog,
    lookupExternalAdminUserTarget,
    resetExternalAdminUserPassword,
    updateExternalAdminUserStatus,
    updateExternalAdminUserPermissions,
} from "./api";

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

test("loads the backend-driven permission catalog and sends an explicit permission snapshot", async () => {
    vi.stubGlobal(
        "fetch",
        vi.fn()
            .mockResolvedValueOnce(
                envelope({
                    items: [
                        {
                            capabilities: ["user:list"],
                            code: "user:list",
                            defaultGranted: true,
                            dependencies: [],
                            group: "用户管理",
                            label: "用户列表",
                        },
                    ],
                    total: 1,
                }),
            )
            .mockResolvedValueOnce(envelope({ accountId: "71", permissions: ["user:list"], revision: 4 }))
            .mockResolvedValueOnce(envelope({ ...externalUserFixture(), permissions: [] })),
    );

    const catalog = await listExternalAdminPermissionCatalog("fami");
    const current = await getExternalAdminUserPermissions("fami", 71);
    const updated = await updateExternalAdminUserPermissions("fami", 71, [], 4);

    const calls = vi.mocked(fetch).mock.calls;
    expect(calls.map(([, init]) => init?.method)).toEqual(["GET", "GET", "PUT"]);
    expect(String(calls[0][0])).toContain("/api/v1/admin/external-admin-users/permission-catalog");
    expect(String(calls[1][0])).toContain("/api/v1/admin/external-admin-users/71/permissions");
    expect(String(calls[2][0])).toContain("/api/v1/admin/external-admin-users/71/permissions");
    expect(requestBody(calls[2][1])).toEqual({ expectedRevision: 4, permissions: [] });
    expect(catalog).toEqual({
        items: [
            {
                capabilities: ["user:list"],
                code: "user:list",
                defaultGranted: true,
                dependencies: [],
                group: "用户管理",
                label: "用户列表",
            },
        ],
        total: 1,
    });
    expect(current).toEqual({ accountId: "71", permissions: ["user:list"], revision: 4 });
    expect(updated.permissions).toEqual([]);
});

test("external admin APIs pin every read and write to the explicit App scope", async () => {
    setSelectedAppCode("lalu");
    const externalUser = externalUserFixture();
    vi.stubGlobal(
        "fetch",
        vi.fn()
            .mockResolvedValueOnce(envelope({ items: [externalUser], page: 1, page_size: 50, total: 1 }))
            .mockResolvedValueOnce(envelope({ linked_user: externalUser.linked_user }))
            .mockResolvedValueOnce(envelope(externalUser, 201))
            .mockResolvedValueOnce(envelope({ ...externalUser, status: "disabled" }))
            .mockResolvedValueOnce(envelope(externalUser)),
    );

    const list = await listExternalAdminUsers(" Huwaa ", {
        keyword: "ops.fami",
        page: 1,
        page_size: 50,
        status: "active",
    });
    const target = await lookupExternalAdminUserTarget("huwaa", "VIP-1001");
    await createExternalAdminUser("huwaa", {
        password: "StrongPass123!",
        targetUserId: "user-1001",
        username: "ops.fami",
    });
    await updateExternalAdminUserStatus("huwaa", 71, "disabled");
    await resetExternalAdminUserPassword("huwaa", 71, "NextStrongPass123!");

    const calls = vi.mocked(fetch).mock.calls;
    expect(calls.map(([, init]) => init?.method)).toEqual(["GET", "GET", "POST", "PATCH", "POST"]);
    calls.forEach(([, init]) => {
        expect(init?.headers).toMatchObject({ "X-App-Code": "huwaa" });
    });
    expect(String(calls[0][0])).toContain("/api/v1/admin/external-admin-users?");
    expect(String(calls[0][0])).toContain("keyword=ops.fami");
    expect(String(calls[0][0])).toContain("status=active");
    expect(String(calls[1][0])).toContain("/api/v1/admin/external-admin-users/target?display_user_id=VIP-1001");
    expect(String(calls[3][0])).toContain("/api/v1/admin/external-admin-users/71/status");
    expect(String(calls[4][0])).toContain("/api/v1/admin/external-admin-users/71/password");
    expect(requestBody(calls[2][1])).toEqual({
        password: "StrongPass123!",
        targetUserId: "user-1001",
        username: "ops.fami",
    });
    expect(requestBody(calls[3][1])).toEqual({ status: "disabled" });
    expect(requestBody(calls[4][1])).toEqual({ password: "NextStrongPass123!" });
    expect(list).toMatchObject({
        page: 1,
        pageSize: 50,
        total: 1,
        items: [
            {
                appCode: "huwaa",
                createdAtMs: 1784073600000,
                createdByAdminId: 9,
                id: 71,
                linkedUser: {
                    defaultDisplayUserId: "1001",
                    prettyDisplayUserId: "VIP-1001",
                    userId: "user-1001",
                },
                permissions: ["user:list", "room:edit"],
                permissionRevision: 3,
                status: "active",
                username: "ops.fami",
            },
        ],
    });
    expect(target).toMatchObject({
        defaultDisplayUserId: "1001",
        prettyDisplayUserId: "VIP-1001",
        userId: "user-1001",
    });
});

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

function requestBody(init: RequestInit | undefined) {
    return JSON.parse(String(init?.body || "{}"));
}

function externalUserFixture() {
    return {
        app_code: "huwaa",
        created_at_ms: "1784073600000",
        created_by_admin_id: 9,
        id: 71,
        last_login_at_ms: null,
        linked_user: {
            avatar: "https://cdn.example.com/u.png",
            default_display_user_id: "1001",
            display_user_id: "VIP-1001",
            pretty_display_user_id: "VIP-1001",
            pretty_id: "pretty-1",
            status: "active",
            user_id: "user-1001",
            username: "Fami user",
        },
        permissions: ["user:list", "room:edit"],
        permission_revision: 3,
        status: "active",
        updated_at_ms: "1784077200000",
        username: "ops.fami",
    };
}
