import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { afterEach, expect, test, vi } from "vitest";
import { COIN_SELLER_RECHARGE_PROVIDER_CURRENCIES } from "../constants.js";
import { FinanceCoinSellerRechargeOrderList } from "./FinanceCoinSellerRechargeOrderList.jsx";

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

test("coin seller recharge order create dialog verifies receipt before create", async () => {
    const nowMS = new Date(2026, 6, 13, 12, 30, 0, 0).getTime();
    const historicalOrderMS = new Date(2026, 6, 11, 12, 30, 0, 0).getTime();
    vi.spyOn(Date, "now").mockReturnValue(nowMS);
    const onCreate = vi.fn(async () => ({ id: "order-2" }));
    const onQuote = vi.fn(async () => ({
        coinAmount: 1000000,
        coinsPerUsd: 100000,
        matchedUserId: "10001",
        rateSource: "whitelist",
    }));
    const onVerifyReceipt = vi.fn(async () => ({
        currencyCode: "PHP",
        providerAmountMinor: 4800,
        providerOrderId: "V5-001",
        status: "paid",
        verified: true,
    }));
    render(
        <FinanceCoinSellerRechargeOrderList
            {...baseProps()}
            onCreate={onCreate}
            onQuote={onQuote}
            onVerifyReceipt={onVerifyReceipt}
        />,
    );

    fireEvent.click(screen.getByRole("button", { name: "创建币商充值" }));
    fireEvent.mouseDown(screen.getByRole("combobox", { name: "支付渠道" }));
    fireEvent.click(screen.getByRole("option", { name: "V5Pay" }));

    expect(screen.getByRole("combobox", { name: "币种" })).toBeInTheDocument();
    expect(screen.getByRole("spinbutton", { name: "币种金额" })).toBeInTheDocument();
    expect(screen.queryByRole("textbox", { name: "支付类型" })).not.toBeInTheDocument();
    expect(screen.queryByRole("textbox", { name: "订单日期" })).not.toBeInTheDocument();

    fireEvent.change(screen.getByRole("textbox", { name: "目标用户 ID" }), { target: { value: "10001" } });
    fireEvent.change(screen.getByRole("spinbutton", { name: "USD 金额" }), { target: { value: "10" } });
    fireEvent.click(screen.getByRole("button", { name: /订单时间/ }));
    fireEvent.click(screen.getByRole("button", { name: "2026-07-11" }));
    fireEvent.click(screen.getByRole("button", { name: "确定" }));
    await waitFor(() => expect(screen.getByRole("status", { name: "充值金币" })).toHaveTextContent("1,000,000"));
    expect(screen.getByText(/白名单 10001.*1 USD = 100,000 金币/)).toBeInTheDocument();
    fireEvent.mouseDown(screen.getByRole("combobox", { name: "币种" }));
    fireEvent.click(await screen.findByRole("option", { name: "PHP" }));
    fireEvent.change(screen.getByRole("spinbutton", { name: "币种金额" }), { target: { value: "48" } });
    fireEvent.change(screen.getByRole("textbox", { name: "三方订单号" }), { target: { value: "V5-001" } });
    fireEvent.change(screen.getByRole("textbox", { name: "备注" }), { target: { value: "补单，不发金币" } });
    expect(screen.getByRole("button", { name: "创建" })).toBeDisabled();

    fireEvent.click(screen.getByRole("button", { name: "校验" }));
    await screen.findByText(/校验通过/);
    await waitFor(() => expect(screen.getByRole("button", { name: "创建" })).not.toBeDisabled());
    expect(onVerifyReceipt).toHaveBeenCalledWith({
        appCode: "lalu",
        externalOrderNo: "V5-001",
        orderDateMs: historicalOrderMS,
        providerAmountMinor: 4800,
        providerCode: "v5pay",
        providerCurrencyCode: "PHP",
        usdAmount: 10,
    });
    fireEvent.click(screen.getByRole("button", { name: "创建" }));
    await waitFor(() =>
        expect(onCreate).toHaveBeenCalledWith({
            appCode: "lalu",
            externalOrderNo: "V5-001",
            isMakeup: false,
            orderDateMs: historicalOrderMS,
            providerAmountMinor: 4800,
            providerCode: "v5pay",
            providerCurrencyCode: "PHP",
            remark: "补单，不发金币",
            targetUserId: "10001",
            usdAmount: 10,
        }),
    );
}, 10000);

test("MiFaPay and V5Pay expose the complete runtime currency list", () => {
    const runtimeCurrencies = Intl.supportedValuesOf("currency");

    expect(COIN_SELLER_RECHARGE_PROVIDER_CURRENCIES.mifapay).toEqual(expect.arrayContaining(runtimeCurrencies));
    expect(COIN_SELLER_RECHARGE_PROVIDER_CURRENCIES.v5pay).toEqual(expect.arrayContaining(runtimeCurrencies));
    expect(COIN_SELLER_RECHARGE_PROVIDER_CURRENCIES.mifapay).toContain("BRL");
    expect(COIN_SELLER_RECHARGE_PROVIDER_CURRENCIES.v5pay).toContain("BRL");
});

test("makeup order keeps zero coins while creating a normal recharge record", async () => {
    const nowMS = new Date(2026, 6, 13, 9, 0, 0, 0).getTime();
    vi.spyOn(Date, "now").mockReturnValue(nowMS);
    const onCreate = vi.fn(async () => ({ id: "makeup-order" }));
    const onQuote = vi.fn();
    const onVerifyReceipt = vi.fn(async () => ({ status: "paid", verified: true }));
    render(
        <FinanceCoinSellerRechargeOrderList
            {...baseProps()}
            onCreate={onCreate}
            onQuote={onQuote}
            onVerifyReceipt={onVerifyReceipt}
        />,
    );

    fireEvent.click(screen.getByRole("button", { name: "创建币商充值" }));
    fireEvent.click(screen.getByRole("button", { name: "补单" }));
    expect(screen.getByRole("button", { name: "补单" })).toHaveAttribute("aria-pressed", "true");
    expect(screen.getByRole("status", { name: "充值金币" })).toHaveTextContent("0");
    expect(screen.getByText("补单不发放金币，充值金额仍正常计入统计")).toBeInTheDocument();

    fireEvent.change(screen.getByRole("textbox", { name: "目标用户 ID" }), { target: { value: "123456" } });
    fireEvent.change(screen.getByRole("spinbutton", { name: "USD 金额" }), { target: { value: "150" } });
    fireEvent.mouseDown(screen.getByRole("combobox", { name: "币种" }));
    fireEvent.click(await screen.findByRole("option", { name: "PHP" }));
    fireEvent.change(screen.getByRole("spinbutton", { name: "币种金额" }), { target: { value: "7200" } });
    fireEvent.change(screen.getByRole("textbox", { name: "三方订单号" }), { target: { value: "MIFA-MAKEUP-001" } });
    fireEvent.click(screen.getByRole("button", { name: "校验" }));
    await screen.findByText(/校验通过/);
    fireEvent.click(screen.getByRole("button", { name: "创建" }));

    await waitFor(() =>
        expect(onCreate).toHaveBeenCalledWith({
            appCode: "lalu",
            externalOrderNo: "MIFA-MAKEUP-001",
            isMakeup: true,
            orderDateMs: nowMS,
            providerAmountMinor: 720000,
            providerCode: "mifapay",
            providerCurrencyCode: "PHP",
            targetUserId: "123456",
            usdAmount: 150,
        }),
    );
    expect(onQuote).not.toHaveBeenCalled();
});

test("USDT chain selector exposes Binance Off-chain as an explicit verification source", async () => {
    render(<FinanceCoinSellerRechargeOrderList {...baseProps()} />);

    fireEvent.click(screen.getByRole("button", { name: "创建币商充值" }));
    fireEvent.mouseDown(screen.getByRole("combobox", { name: "支付渠道" }));
    fireEvent.click(screen.getByRole("option", { name: "USDT" }));
    fireEvent.mouseDown(screen.getByRole("combobox", { name: "USDT 链" }));

    expect(screen.getByRole("option", { name: "Binance 站内转账 / Off-chain" })).toBeInTheDocument();
    expect(screen.getByRole("option", { name: "Binance Pay / C2C" })).toBeInTheDocument();
});

test("coin seller recharge order actions follow verify and grant status", () => {
    const onVerify = vi.fn();
    const onGrant = vi.fn();

    render(
        <FinanceCoinSellerRechargeOrderList
            {...baseProps({
                orders: {
                    items: [
                        orderFixture({ id: "pending", verifyStatus: "pending", grantStatus: "pending" }),
                        orderFixture({ id: "verified", verifyStatus: "verified", grantStatus: "pending" }),
                    ],
                    page: 1,
                    pageSize: 50,
                    total: 2,
                },
            })}
            onGrant={onGrant}
            onVerify={onVerify}
        />,
    );

    const verifyButtons = screen.getAllByRole("button", { name: "校验" });
    const grantButtons = screen.getAllByRole("button", { name: "发放" });
    const actionHeader = screen.getByRole("columnheader", { name: "操作" });
    const actionCell = verifyButtons[0].closest("td");
    fireEvent.click(verifyButtons[0]);
    fireEvent.click(grantButtons[1]);

    expect(actionHeader).toHaveClass("finance-flat-table__actions-cell");
    expect(actionCell).toHaveClass("finance-flat-table__actions-cell");
    expect(onVerify).toHaveBeenCalledWith(expect.objectContaining({ id: "pending" }));
    expect(screen.getByRole("dialog", { name: "发放金币验证" })).toBeInTheDocument();
    expect(onGrant).not.toHaveBeenCalled();
    expect(screen.getAllByText("人工补单")[0]).toBeInTheDocument();
    expect(grantButtons[0]).toBeDisabled();
    expect(verifyButtons[1]).toBeDisabled();
});

test("coin grant requires exact text and a final confirmation before calling the API", () => {
    const onGrant = vi.fn();

    render(
        <FinanceCoinSellerRechargeOrderList
            {...baseProps({
                orders: {
                    items: [
                        orderFixture({
                            coinAmount: 80000,
                            grantStatus: "pending",
                            id: "7777",
                            targetDisplayUserId: "7777",
                            usdAmount: "1.00",
                            verifyStatus: "verified",
                        }),
                    ],
                    page: 1,
                    pageSize: 50,
                    total: 1,
                },
            })}
            onGrant={onGrant}
        />,
    );

    fireEvent.click(screen.getByRole("button", { name: "发放" }));

    const statement = "本订单金额1USDT将会向用户7777的币商账户发放80000金币";
    const input = screen.getByRole("textbox", { name: "完整输入发放文字" });
    const firstConfirm = screen.getByRole("button", { name: "确认" });
    expect(screen.getByText(statement)).toBeInTheDocument();
    expect(firstConfirm).toBeDisabled();

    fireEvent.change(input, { target: { value: `${statement} ` } });
    expect(firstConfirm).toBeDisabled();
    fireEvent.change(input, { target: { value: statement } });
    expect(firstConfirm).not.toBeDisabled();
    fireEvent.click(firstConfirm);

    expect(screen.getByRole("dialog", { name: "确认发放金币" })).toBeInTheDocument();
    expect(onGrant).not.toHaveBeenCalled();
    fireEvent.click(screen.getByRole("button", { name: "确认发放" }));
    expect(onGrant).toHaveBeenCalledTimes(1);
    expect(onGrant).toHaveBeenCalledWith(expect.objectContaining({ id: "7777", coinAmount: 80000 }));
});

test("zero coin seller recharge order completes makeup without confirmation", () => {
    const onGrant = vi.fn();

    render(
        <FinanceCoinSellerRechargeOrderList
            {...baseProps({
                orders: {
                    items: [
                        orderFixture({ coinAmount: 0, grantStatus: "pending", id: "makeup", verifyStatus: "verified" }),
                    ],
                    page: 1,
                    pageSize: 50,
                    total: 1,
                },
            })}
            onGrant={onGrant}
        />,
    );

    fireEvent.click(screen.getByRole("button", { name: "完成补单" }));

    expect(screen.getByText("USD 10.00")).toHaveClass("finance-recharge-amount");
    expect(screen.getByText("0 金币（补单）")).not.toHaveClass("finance-recharge-coins--positive");
    expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
    expect(onGrant).toHaveBeenCalledWith(expect.objectContaining({ id: "makeup", coinAmount: 0 }));
});

test("highlights recharge amount and only non-zero coins", () => {
    render(<FinanceCoinSellerRechargeOrderList {...baseProps()} />);

    expect(screen.getByText("USD 10.00")).toHaveClass("finance-recharge-amount");
    expect(screen.getByText("100,000 金币")).toHaveClass("finance-recharge-coins--positive");
});

function baseProps(overrides = {}) {
    return {
        actionLoading: "",
        apps: [{ appCode: "lalu", appName: "lalu" }],
        canCreate: true,
        canConfigureExchangeRate: false,
        canGrant: true,
        canUpdateUSDTAddress: false,
        canVerify: true,
        error: "",
        filters: {
            appCode: "",
            grantStatus: "",
            keyword: "",
            page: 1,
            providerCode: "",
            status: "",
            verifyStatus: "",
        },
        loading: false,
        onCreate: vi.fn(),
        onLoadExchangeRate: vi.fn(async () => ({ appCode: "lalu", tiers: [], whitelist: [] })),
        onLoadUSDTAddresses: vi.fn(async () => ({ appCode: "lalu", items: [] })),
        onFiltersChange: vi.fn(),
        onGrant: vi.fn(),
        onReload: vi.fn(),
        onQuote: vi.fn(async () => ({ coinAmount: 800000, coinsPerUsd: 80000, rateSource: "tier" })),
        onSaveExchangeRate: vi.fn(),
        onSaveUSDTAddress: vi.fn(),
        onVerify: vi.fn(),
        onVerifyReceipt: vi.fn(),
        orders: {
            items: [orderFixture()],
            page: 1,
            pageSize: 50,
            total: 1,
        },
        ...overrides,
    };
}

function orderFixture(overrides = {}) {
    return {
        appCode: "lalu",
        coinAmount: 100000,
        createdAtMs: 1760000000000,
        externalOrderNo: "MIFA-001",
        grantStatus: "pending",
        id: "order-1",
        providerCode: "mifapay",
        remark: "人工补单",
        status: "pending",
        targetDisplayUserId: "165075",
        targetUserId: "10001",
        usdAmount: "10.00",
        verifyStatus: "pending",
        ...overrides,
    };
}
