import { render, screen, waitFor, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MemoryRouter } from "react-router-dom";
import { afterEach, expect, test, vi } from "vitest";
import { AppProviders } from "@/app/providers.jsx";
import { SystemMessagePushPage } from "./SystemMessagePushPage.jsx";

vi.mock("@/app/auth/AuthProvider.jsx", () => ({
    AuthProvider: ({ children }) => children,
    useAuth: () => ({ can: () => true }),
}));

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

test("submits all registered users payload with fixed system message type", async () => {
    const user = userEvent.setup();
    vi.stubGlobal("fetch", createFanoutFetch({ target_scope: "all_registered_users" }));

    renderPage();
    await user.type(screen.getByRole("textbox", { name: "标题" }), "维护通知");
    await user.type(screen.getByRole("textbox", { name: "摘要" }), "今晚 23:00 维护");
    await user.click(screen.getByRole("button", { name: "发送" }));
    await confirmSend(user);

    await waitFor(() =>
        expect(fanoutPostBodies()).toEqual([
            expect.objectContaining({
                message_type: "system",
                producer_event_type: "admin_full_server_notice",
                target_scope: "all_registered_users",
                title: "维护通知",
            }),
        ]),
    );
});

test("submits specified users after parsing and deduping separators", async () => {
    const user = userEvent.setup();
    vi.stubGlobal("fetch", createFanoutFetch({ target_scope: "user_ids" }));

    renderPage();
    await user.click(screen.getByRole("combobox", { name: "发送范围" }));
    await user.click(screen.getByRole("option", { name: "指定用户" }));
    await user.type(screen.getByRole("textbox", { name: "用户 ID 列表" }), "325379237278126080, 42，42");
    await user.type(screen.getByRole("textbox", { name: "标题" }), "指定用户通知");
    await user.type(screen.getByRole("textbox", { name: "摘要" }), "只发给指定用户");
    await user.click(screen.getByRole("button", { name: "发送" }));
    await confirmSend(user);

    await waitFor(() =>
        expect(fanoutPostBodies()).toEqual([
            expect.objectContaining({
                message_type: "system",
                target_scope: "user_ids",
                user_ids: ["325379237278126080", "42"],
            }),
        ]),
    );
});

test("blocks specified users submit when user ID list is empty", async () => {
    const user = userEvent.setup();
    vi.stubGlobal("fetch", createFanoutFetch({ target_scope: "user_ids" }));

    renderPage();
    await user.click(screen.getByRole("combobox", { name: "发送范围" }));
    await user.click(screen.getByRole("option", { name: "指定用户" }));
    await user.type(screen.getByRole("textbox", { name: "标题" }), "指定用户通知");
    await user.type(screen.getByRole("textbox", { name: "摘要" }), "只发给指定用户");
    await user.click(screen.getByRole("button", { name: "发送" }));

    await waitFor(() => expect(screen.getByText("用户 ID 列表不能为空")).toBeInTheDocument());
    expect(fanoutPostBodies()).toHaveLength(0);
});

function renderPage() {
    return render(
        <AppProviders>
            <MemoryRouter>
                <SystemMessagePushPage />
            </MemoryRouter>
        </AppProviders>,
    );
}

async function confirmSend(user) {
    const dialog = await screen.findByRole("dialog", { name: "发送系统消息" });
    await user.click(within(dialog).getByRole("button", { name: "发送" }));
}

function fanoutPostBodies() {
    return vi
        .mocked(fetch)
        .mock.calls.filter(
            ([url, init]) =>
                String(url).includes("/api/v1/admin/operations/full-server-notices/fanout") && init?.method === "POST",
        )
        .map(([, init]) => JSON.parse(String(init?.body)));
}

function createFanoutFetch({ target_scope }) {
    return vi.fn(
        async () =>
            new Response(
                JSON.stringify({
                    code: 0,
                    data: {
                        command_id: "admin_notice_test",
                        created: true,
                        job_id: "mfan_test",
                        message_type: "system",
                        status: "pending",
                        target_scope,
                    },
                }),
            ),
    );
}
