import { fireEvent, render, screen } from "@testing-library/react";
import { afterEach, expect, test, vi } from "vitest";
import { AppUserListPage } from "./AppUserListPage.jsx";
import { ToastProvider } from "@/shared/ui/ToastProvider.jsx";
import { useAppUsersPage } from "@/features/app-users/hooks/useAppUsersPage.js";

const mocks = vi.hoisted(() => ({
    ledgerTable: vi.fn(),
    openCoinLedger: vi.fn(),
}));

vi.mock("@/features/app-users/hooks/useAppUsersPage.js", () => ({
    useAppUsersPage: vi.fn(),
}));

vi.mock("@/features/operations/components/CoinLedgerTable.jsx", () => ({
    CoinLedgerTable: (props) => {
        mocks.ledgerTable(props);
        return <div data-testid="coin-ledger-table">{props.userId}</div>;
    },
}));

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

test("clicking an app user's coin opens the coin ledger drawer", () => {
    vi.mocked(useAppUsersPage).mockReturnValue(pageFixture());

    render(
        <ToastProvider>
            <AppUserListPage />
        </ToastProvider>,
    );

    expect(screen.getByText("VIP 2")).toBeInTheDocument();
    expect(screen.getByText("VIP888")).toBeInTheDocument();
    expect(screen.getByText("公会长、BD")).toBeInTheDocument();
    expect(screen.getByRole("button", { name: "调整财富/魅力/游戏等级列宽" })).toBeInTheDocument();
    expect(screen.getByLabelText("女，24 岁")).toBeInTheDocument();
    expect(screen.getByText("财富")).toBeInTheDocument();
    expect(screen.getByRole("button", { name: "调整最新成功登录列宽" })).toBeInTheDocument();
    fireEvent.click(screen.getByRole("button", { name: "查看 d 的金币流水" }));

    expect(mocks.openCoinLedger).toHaveBeenCalledWith(expect.objectContaining({ userId: "10001" }));
});

test("coin ledger drawer passes the active app user to the shared ledger table", () => {
    const activeUser = userFixture();
    vi.mocked(useAppUsersPage).mockReturnValue(
        pageFixture({
            activeAction: "coin-ledger",
            activeUser,
        }),
    );

    render(
        <ToastProvider>
            <AppUserListPage />
        </ToastProvider>,
    );

    expect(screen.getByTestId("coin-ledger-table")).toHaveTextContent("10001");
    expect(mocks.ledgerTable).toHaveBeenCalledWith(
        expect.objectContaining({ lockedUser: activeUser, userId: "10001" }),
    );
});

test("edit dialog saves profile and temporary levels independently", () => {
    const page = pageFixture({ activeAction: "edit", activeUser: userFixture() });
    vi.mocked(useAppUsersPage).mockReturnValue(page);

    render(
        <ToastProvider>
            <AppUserListPage />
        </ToastProvider>,
    );

    expect(screen.getByText("用户资料")).toBeInTheDocument();
    expect(screen.getByText("等级调整")).toBeInTheDocument();
    expect(screen.getByLabelText("游戏等级（只读）")).toBeDisabled();
    fireEvent.click(screen.getByRole("button", { name: "保存等级" }));
    expect(page.submitLevels).toHaveBeenCalledTimes(1);

    fireEvent.submit(screen.getByRole("button", { name: "保存资料" }).closest("form"));
    expect(page.submitEdit).toHaveBeenCalledTimes(1);
});

test("level-only permission can open level adjustment without exposing country edit", () => {
    const page = pageFixture({
        abilities: { ...pageFixture().abilities, canLevel: true, canUpdate: false },
    });
    vi.mocked(useAppUsersPage).mockReturnValue(page);

    render(
        <ToastProvider>
            <AppUserListPage />
        </ToastProvider>,
    );

    fireEvent.click(screen.getByRole("button", { name: "等级调整" }));
    expect(page.openEdit).toHaveBeenCalledWith(expect.objectContaining({ userId: "10001" }));
    expect(screen.queryByRole("button", { name: "阿拉伯联合酋长国" })).not.toBeInTheDocument();
});

function pageFixture(patch = {}) {
    return {
        abilities: {
            canCoinLedger: true,
            canExport: true,
            canLevel: true,
            canPassword: true,
            canStatus: true,
            canUpdate: true,
            canUpload: true,
            canView: true,
        },
        activeAction: "",
        activeUser: null,
        banForm: { expiresAtLocal: "", mode: "permanent", reason: "" },
        batchBan: vi.fn(),
        changeLocationFilter: vi.fn(),
        changeQuery: vi.fn(),
        changeSort: vi.fn(),
        changeStatus: vi.fn(),
        changeTimeRange: vi.fn(),
        closeAction: vi.fn(),
        countryForm: { country: "" },
        countryOptions: [],
        data: { items: [userFixture()], page: 1, pageSize: 50, total: 1 },
        editForm: { avatar: "", gender: "", username: "" },
        exportUsers: vi.fn(),
        error: null,
        loading: false,
        loadingAction: "",
        loadingCountries: false,
        loadingRegions: false,
        levelForm: {
            charm: { durationDays: "7", enabled: false, level: "4" },
            reason: "",
            wealth: { durationDays: "7", enabled: false, level: "5" },
        },
        locationFilterOptions: [],
        locationFilterValue: "",
        openCoinLedger: mocks.openCoinLedger,
        openCountry: vi.fn(),
        openEdit: vi.fn(),
        openPassword: vi.fn(),
        page: 1,
        passwordForm: { password: "" },
        query: "",
        regionOptions: [],
        reload: vi.fn(),
        resetFilters: vi.fn(),
        selectedUserIds: [],
        setBanForm: vi.fn(),
        setCountryForm: vi.fn(),
        setEditForm: vi.fn(),
        setLevelForm: vi.fn(),
        setPage: vi.fn(),
        setPasswordForm: vi.fn(),
        setSelectedUserIds: vi.fn(),
        sortBy: "created_at",
        sortDirection: "desc",
        status: "",
        submitBan: vi.fn(),
        submitCountry: vi.fn(),
        submitEdit: vi.fn(),
        submitLevels: vi.fn(),
        submitPassword: vi.fn(),
        timeRange: { endMs: "", startMs: "" },
        toggleBan: vi.fn(),
        ...patch,
    };
}

function userFixture() {
    return {
        age: 24,
        avatar: "",
        ban: { active: false, expiresAtMs: 0, permanent: false },
        coin: 223437,
        country: "AE",
        countryDisplayName: "阿拉伯联合酋长国",
        createdAtMs: 1779322523000,
        defaultDisplayUserId: "163337",
        displayUserId: "163337",
        gender: "female",
        lastActiveAtMs: 1781325798000,
        lastLoginAtMs: 1781325700000,
        lastOperatedAtMs: 1781325750000,
        lastOperator: { action: "update", adminId: "7", name: "雷乐" },
        levels: {
            charm: { displayLevel: 3, realLevel: 3, track: "charm" },
            game: { displayLevel: 6, realLevel: 6, track: "game" },
            wealth: { displayLevel: 4, realLevel: 4, track: "wealth" },
        },
        prettyDisplayUserId: "VIP888",
        prettyId: "pretty-888",
        regionId: 2,
        regionName: "中东区",
        roles: ["公会长", "BD"],
        status: "active",
        userId: "10001",
        username: "d",
        vip: { active: true, level: 2, name: "白银会员" },
    };
}
