const {
    removeWalletFromState,
    broadcastActiveChanged,
} = require("../src/shared/walletDelete");

// Fixed addresses — never used for anything but these tests.
const A0 = "0x66133E8ea0f5D1d612D2502a968757D1048c214a";
const A1 = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
const B0 = "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599";
const C0 = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";

function wallet(name, addresses) {
    return {
        name,
        addresses: addresses.map((address) => ({ address })),
    };
}

// A three-wallet state; wallet A is an HD wallet with two addresses.
function makeState(overrides = {}) {
    return {
        hasWallet: true,
        wallets: [wallet("A", [A0, A1]), wallet("B", [B0]), wallet("C", [C0])],
        selectedWallet: 0,
        selectedAddress: 0,
        activeAddress: A0,
        allowedSites: {
            [A0]: ["a.example"],
            [A1]: ["b.example"],
            [B0]: ["c.example"],
        },
        deniedSites: { [A1]: ["d.example"], [C0]: ["e.example"] },
        ...overrides,
    };
}

describe("removeWalletFromState", () => {
    test("deleting the last wallet clears hasWallet", () => {
        const state = makeState({
            wallets: [wallet("A", [A0])],
            allowedSites: { [A0]: ["a.example"] },
            deniedSites: {},
        });

        const { activeAddressChanged } = removeWalletFromState(state, 0);

        expect(state.hasWallet).toBe(false);
        expect(state.wallets).toEqual([]);
        expect(state.selectedWallet).toBeNull();
        expect(state.selectedAddress).toBeNull();
        expect(state.activeAddress).toBeNull();
        expect(activeAddressChanged).toBe(true);
    });

    test("deleting a non-selected wallet leaves the selection intact", () => {
        const state = makeState({
            selectedWallet: 2,
            selectedAddress: 0,
            activeAddress: C0,
        });

        const { activeAddressChanged } = removeWalletFromState(state, 1);

        // Wallet C moved from index 2 to index 1 by the splice.
        expect(state.wallets.map((w) => w.name)).toEqual(["A", "C"]);
        expect(state.selectedWallet).toBe(1);
        expect(state.selectedAddress).toBe(0);
        expect(state.activeAddress).toBe(C0);
        expect(activeAddressChanged).toBe(false);
        expect(state.hasWallet).toBe(true);
    });

    test("deleting a wallet after the selection does not shift it", () => {
        const state = makeState({
            selectedWallet: 1,
            selectedAddress: 0,
            activeAddress: B0,
        });

        const { activeAddressChanged } = removeWalletFromState(state, 2);

        expect(state.selectedWallet).toBe(1);
        expect(state.activeAddress).toBe(B0);
        expect(activeAddressChanged).toBe(false);
    });

    test("deleting the active wallet falls back to the first remaining address", () => {
        const state = makeState({
            selectedWallet: 0,
            selectedAddress: 1,
            activeAddress: A1,
        });

        const { activeAddressChanged } = removeWalletFromState(state, 0);

        expect(state.wallets.map((w) => w.name)).toEqual(["B", "C"]);
        expect(state.selectedWallet).toBe(0);
        expect(state.selectedAddress).toBe(0);
        expect(state.activeAddress).toBe(B0);
        expect(activeAddressChanged).toBe(true);
        expect(state.hasWallet).toBe(true);
    });

    test("site permissions are dropped for every address of the wallet", () => {
        const state = makeState();

        removeWalletFromState(state, 0);

        expect(state.allowedSites).toEqual({ [B0]: ["c.example"] });
        expect(state.deniedSites).toEqual({ [C0]: ["e.example"] });
    });
});

describe("broadcastActiveChanged", () => {
    afterEach(() => {
        delete global.chrome;
    });

    test("sends AUTISTMASK_ACTIVE_CHANGED to the background", () => {
        const sendMessage = jest.fn();
        global.chrome = { runtime: { sendMessage } };

        broadcastActiveChanged();

        expect(sendMessage).toHaveBeenCalledWith({
            type: "AUTISTMASK_ACTIVE_CHANGED",
        });
    });
});
