import { fireEvent, render, screen } from "@testing-library/react";
import { afterEach, expect, test, vi } from "vitest";
import { ResourceGrantListPage } from "./ResourceGrantListPage.jsx";
import { useResourceGrantListPage } from "@/features/resources/hooks/useResourcePages.js";

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

vi.mock("@/features/resources/hooks/useResourcePages.js", () => ({
    useResourceGrantListPage: vi.fn(),
}));

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

test("resource grant list shows revoke for succeeded resource and resource group grants", () => {
    const eligibleGroup = grantFixture({
        grantId: "rgr_group_ok",
        grantSubjectType: "resource_group",
        status: "succeeded",
    });
    const eligibleResource = grantFixture({
        grantId: "rgr_resource_ok",
        grantSubjectType: "resource",
        status: "succeeded",
    });
    vi.mocked(useResourceGrantListPage).mockReturnValue(
        pageFixture({
            data: {
                items: [
                    eligibleGroup,
                    eligibleResource,
                    grantFixture({
                        grantId: "rgr_group_revoked",
                        grantSubjectType: "resource_group",
                        status: "revoked",
                    }),
                ],
                page: 1,
                pageSize: 50,
                total: 3,
            },
        }),
    );

    render(<ResourceGrantListPage />);

    expect(screen.getByText("已撤销")).toBeInTheDocument();
    const revokeButtons = screen.getAllByLabelText("撤销");
    expect(revokeButtons).toHaveLength(2);

    fireEvent.click(revokeButtons[0]);
    fireEvent.click(revokeButtons[1]);

    expect(mocks.revokeGrant).toHaveBeenNthCalledWith(1, eligibleGroup);
    expect(mocks.revokeGrant).toHaveBeenNthCalledWith(2, eligibleResource);
});

test("resource grant list hides revoke without permission", () => {
    vi.mocked(useResourceGrantListPage).mockReturnValue(
        pageFixture({
            abilities: { canCreateGrant: false, canRevokeGrant: false },
            data: {
                items: [grantFixture({ grantSubjectType: "resource_group", status: "succeeded" })],
                page: 1,
                pageSize: 50,
                total: 1,
            },
        }),
    );

    render(<ResourceGrantListPage />);

    expect(screen.queryByLabelText("撤销")).not.toBeInTheDocument();
});

test("resource grant list renders readable source, reason, and granted items", () => {
    vi.mocked(useResourceGrantListPage).mockReturnValue(
        pageFixture({
            data: {
                items: [
                    grantFixture({
                        grantId: "rgr_1234567890abcdef",
                        commandId: "seven_day_checkin_1782448934991_9b39c38",
                        grantSource: "seven_day_checkin",
                        grantSubjectId: "18",
                        grantSubjectType: "resource_group",
                        items: [
                            {
                                grantItemId: 1,
                                quantity: 100,
                                resourceId: 0,
                                resourceSnapshotJson: JSON.stringify({
                                    wallet_asset_type: "COIN",
                                    wallet_asset_amount: 100,
                                }),
                            },
                            {
                                durationMs: 7 * 24 * 60 * 60 * 1000,
                                grantItemId: 2,
                                quantity: 1,
                                resourceId: 385,
                                resourceSnapshotJson: JSON.stringify({
                                    Name: "星光头像框",
                                    PreviewURL: "https://media.haiyihy.com/star-frame.png",
                                    ResourceType: "avatar_frame",
                                }),
                            },
                        ],
                        operator: { name: "后台用户", source: "admin", userId: "7" },
                        reason: "seven_day_checkin",
                    }),
                ],
                page: 1,
                pageSize: 50,
                total: 1,
            },
        }),
    );

    render(<ResourceGrantListPage />);

    expect(screen.getAllByText("七日签到")).toHaveLength(2);
    expect(screen.getByText("资源组 · 七日签到")).toBeInTheDocument();
    expect(screen.getByText("资源组 ID 18")).toBeInTheDocument();
    expect(screen.getByText("金币 100")).toBeInTheDocument();
    expect(screen.getByText("星光头像框 x1 · 头像框 · 7天")).toBeInTheDocument();
    expect(screen.queryByText("0 / 100")).not.toBeInTheDocument();
    expect(screen.queryByText("rgr_1234567890abcdef")).not.toBeInTheDocument();
    expect(screen.queryByText("seven_day_checkin_1782448934991_9b39c38")).not.toBeInTheDocument();
    expect(screen.queryByText("后台用户")).not.toBeInTheDocument();
    expect(document.querySelector('img[src="https://media.haiyihy.com/star-frame.png"]')).toBeInTheDocument();
});

test("resource grant list keeps operator only for user initiated manager grants", () => {
    vi.mocked(useResourceGrantListPage).mockReturnValue(
        pageFixture({
            data: {
                items: [
                    grantFixture({
                        grantId: "rgr_manager",
                        grantSource: "manager_center",
                        operator: {
                            source: "manager_center",
                            userId: "328151620022083584",
                            username: "Manager A",
                        },
                    }),
                ],
                page: 1,
                pageSize: 50,
                total: 1,
            },
        }),
    );

    render(<ResourceGrantListPage />);

    expect(screen.getByText("Manager A")).toBeInTheDocument();
});

test("resource grant dialog shows vip subject and level selector", () => {
    vi.mocked(useResourceGrantListPage).mockReturnValue(
        pageFixture({
            activeAction: "create",
            form: grantFormFixture({ subjectType: "vip", vipLevel: "5" }),
            vipLevelOptions: [{ level: 5, name: "黄金VIP", status: "active" }],
        }),
    );

    render(<ResourceGrantListPage />);

    expect(screen.getByText("VIP等级")).toBeInTheDocument();
    expect(screen.getByText("VIP5 · 黄金VIP")).toBeInTheDocument();
});

test("fami resource grant dialog exposes vip trial card level and duration", () => {
    vi.mocked(useResourceGrantListPage).mockReturnValue(
        pageFixture({
            activeAction: "create",
            form: grantFormFixture({
                durationDays: "20",
                subjectType: "vip_trial_card",
                vipLevel: "5",
            }),
            vipLevelOptions: [{ level: 5, name: "黄金VIP", status: "active" }],
            vipProgram: { programType: "tiered_privilege_v1", trialCardEnabled: true },
        }),
    );

    render(<ResourceGrantListPage />);

    expect(screen.getByRole("combobox", { name: "对象类型" })).toHaveTextContent("VIP体验卡");
    expect(screen.getByText("VIP5 · 黄金VIP")).toBeInTheDocument();
    expect(screen.getByRole("spinbutton", { name: "有效天数" })).toHaveValue(20);
});

test("resource grant dialog hides vip subject without vip grant permission", () => {
    vi.mocked(useResourceGrantListPage).mockReturnValue(
        pageFixture({
            abilities: { canCreateGrant: true, canGrantVip: false },
            activeAction: "create",
            form: grantFormFixture({ subjectType: "resource" }),
        }),
    );

    render(<ResourceGrantListPage />);

    fireEvent.mouseDown(screen.getByRole("combobox", { name: "对象类型" }));

    expect(screen.queryByRole("option", { name: "VIP" })).not.toBeInTheDocument();
    expect(screen.queryByText("VIP等级")).not.toBeInTheDocument();
});

test("resource grant list renders vip source records and hides revoke", () => {
    vi.mocked(useResourceGrantListPage).mockReturnValue(
        pageFixture({
            data: {
                items: [
                    grantFixture({
                        commandId: "vip_reward:admin_vip_grant:rgr_vip",
                        grantId: "rgr_vip",
                        grantSource: "admin_grant",
                        grantSubjectId: "22",
                        grantSubjectType: "resource_group",
                        reason: "admin_grant",
                        status: "succeeded",
                    }),
                ],
                page: 1,
                pageSize: 50,
                total: 1,
            },
        }),
    );

    render(<ResourceGrantListPage />);

    expect(screen.getAllByText("后台VIP赠送").length).toBeGreaterThanOrEqual(1);
    expect(screen.getByText("VIP奖励资源组 · 后台VIP赠送")).toBeInTheDocument();
    expect(screen.getByText("奖励资源组 ID 22")).toBeInTheDocument();
    expect(screen.queryByLabelText("撤销")).not.toBeInTheDocument();
    expect(screen.queryByText("admin_grant")).not.toBeInTheDocument();
    expect(screen.queryByText("vip_reward:admin_vip_grant:rgr_vip")).not.toBeInTheDocument();
});

function pageFixture(patch = {}) {
    const { abilities: abilityPatch, form: formPatch, ...restPatch } = patch;
    return {
        abilities: {
            canCreateGrant: true,
            canGrantVip: true,
            canRevokeGrant: true,
            ...abilityPatch,
        },
        activeAction: "",
        changeQuery: vi.fn(),
        changeStatus: vi.fn(),
        closeAction: vi.fn(),
        data: { items: [], page: 1, pageSize: 50, total: 0 },
        error: null,
        form: grantFormFixture(formPatch),
        giftOptions: [],
        giftTypeOptions: [],
        groupOptions: [],
        loading: false,
        loadingAction: "",
        openCreateGrant: vi.fn(),
        optionsLoading: false,
        page: 1,
        query: "",
        reload: vi.fn(),
        resetFilters: vi.fn(),
        resourceOptions: [],
        revokeGrant: mocks.revokeGrant,
        setForm: vi.fn(),
        setPage: vi.fn(),
        status: "",
        submitGrant: vi.fn(),
        vipLevelOptions: [],
        vipProgram: { programType: "legacy_timed", trialCardEnabled: false },
        ...restPatch,
    };
}

function grantFormFixture(patch = {}) {
    return {
        durationDays: "7",
        giftIds: [],
        groupId: "",
        quantity: "1",
        reason: "",
        resourceId: "",
        resourceIds: [],
        subjectType: "resource",
        targetUserId: "",
        vipLevel: "",
        ...patch,
    };
}

function grantFixture(patch = {}) {
    return {
        commandId: "resource-group-grant-test",
        createdAtMs: 1782287714973,
        grantId: "rgr_test",
        grantSubjectId: "22",
        grantSubjectType: "resource_group",
        items: [{ grantItemId: 1, quantity: 100, resourceId: 0 }],
        operatorUserId: 7,
        reason: "manual",
        status: "succeeded",
        targetUserId: "318705991371722752",
        ...patch,
    };
}
