import { labelhash, namehash, zeroHash } from 'viem';
import { DAY } from '../../fixtures/constants.js';
import { toLabelId, toNameId } from '../../fixtures/utils.js';
import { CANNOT_UNWRAP, GRACE_PERIOD, PARENT_CANNOT_CONTROL, expectOwnerOf, zeroAccount, } from '../fixtures/utils.js';
export const isWrappedTests = (connection, loadNameWrapperFixture) => {
    describe('isWrapped(bytes32 node)', () => {
        const label = 'something';
        const name = `${label}.eth`;
        async function fixture() {
            const initial = await loadNameWrapperFixture();
            const { nameWrapper, actions } = initial;
            await actions.registerSetupAndWrapName({
                label,
                fuses: CANNOT_UNWRAP,
            });
            const [, , parentExpiry] = await nameWrapper.read.getData([
                toNameId(name),
            ]);
            return { ...initial, parentExpiry };
        }
        const loadFixture = async () => connection.networkHelpers.loadFixture(fixture);
        it('identifies a wrapped .eth name', async () => {
            const { nameWrapper } = await loadFixture();
            await expect(nameWrapper.read.isWrapped([namehash(name)])).resolves.toBe(true);
        });
        it('identifies an expired .eth name as unwrapped', async () => {
            const { nameWrapper, testClient } = await loadFixture();
            await testClient.increaseTime({ seconds: Number(1n * DAY + 1n) });
            await testClient.mine({ blocks: 1 });
            await expect(nameWrapper.read.isWrapped([namehash(name)])).resolves.toBe(false);
        });
        it('identifies an eth name registered on old controller as unwrapped', async () => {
            const { baseRegistrar, nameWrapper, accounts } = await loadNameWrapperFixture();
            await baseRegistrar.write.register([
                toLabelId(label),
                accounts[0].address,
                1n * DAY,
            ]);
            await expectOwnerOf(label).on(baseRegistrar).toBe(accounts[0]);
            await expect(nameWrapper.read.isWrapped([namehash(name)])).resolves.toBe(false);
        });
        it('identifies an unregistered .eth name as unwrapped', async () => {
            const { nameWrapper } = await loadFixture();
            await expect(nameWrapper.read.isWrapped([
                namehash('abcdefghijklmnop.eth'),
            ])).resolves.toBe(false);
        });
        it('identifies an unregistered tld as unwrapped', async () => {
            const { nameWrapper } = await loadFixture();
            await expect(nameWrapper.read.isWrapped([namehash('abc')])).resolves.toBe(false);
        });
        it('identifies a wrapped subname', async () => {
            const { nameWrapper, actions, accounts } = await loadFixture();
            await actions.setSubnodeOwner.onNameWrapper({
                parentName: name,
                label: 'sub',
                owner: accounts[0].address,
                fuses: 0,
                expiry: 0n,
            });
            await expect(nameWrapper.read.isWrapped([
                namehash(`sub.${name}`),
            ])).resolves.toBe(true);
        });
        it('identifies an expired wrapped subname with PCC burnt as unwrapped', async () => {
            const { nameWrapper, actions, accounts, testClient, parentExpiry } = await loadFixture();
            const subname = `sub.${name}`;
            await actions.setSubnodeOwner.onNameWrapper({
                parentName: name,
                label: 'sub',
                owner: accounts[0].address,
                fuses: PARENT_CANNOT_CONTROL,
                expiry: parentExpiry + 100n,
            });
            await expectOwnerOf(subname).on(nameWrapper).toBe(accounts[0]);
            await testClient.increaseTime({
                seconds: Number(DAY + GRACE_PERIOD + 101n),
            });
            await testClient.mine({ blocks: 1 });
            await expectOwnerOf(subname).on(nameWrapper).toBe(zeroAccount);
            await expect(nameWrapper.read.isWrapped([namehash(subname)])).resolves.toBe(false);
        });
    });
    describe('isWrapped(bytes32 parentNode, bytes32 labelhash)', () => {
        const label = 'something';
        const name = `${label}.eth`;
        const sublabel = 'sub';
        const subname = `${sublabel}.${name}`;
        async function fixture() {
            const initial = await loadNameWrapperFixture();
            const { nameWrapper, actions } = initial;
            await actions.registerSetupAndWrapName({
                label,
                fuses: CANNOT_UNWRAP,
            });
            const [, , parentExpiry] = await nameWrapper.read.getData([
                toNameId(name),
            ]);
            return { ...initial, parentExpiry };
        }
        const loadFixture = async () => connection.networkHelpers.loadFixture(fixture);
        it('identifies a wrapped .eth name', async () => {
            const { nameWrapper } = await loadFixture();
            await expect(nameWrapper.read.isWrapped([
                namehash('eth'),
                labelhash(label),
            ])).resolves.toBe(true);
        });
        it('identifies an expired .eth name as unwrapped', async () => {
            const { nameWrapper, testClient } = await loadFixture();
            await testClient.increaseTime({ seconds: Number(1n * DAY + 1n) });
            await testClient.mine({ blocks: 1 });
            await expect(nameWrapper.read.isWrapped([
                namehash('eth'),
                labelhash(label),
            ])).resolves.toBe(false);
        });
        it('identifies an eth name registered on old controller as unwrapped', async () => {
            const { baseRegistrar, nameWrapper, accounts } = await loadNameWrapperFixture();
            await baseRegistrar.write.register([
                toLabelId(label),
                accounts[0].address,
                1n * DAY,
            ]);
            await expectOwnerOf(label).on(baseRegistrar).toBe(accounts[0]);
            await expect(nameWrapper.read.isWrapped([
                namehash('eth'),
                labelhash(label),
            ])).resolves.toBe(false);
        });
        it('identifies an unregistered .eth name as unwrapped', async () => {
            const { nameWrapper } = await loadFixture();
            await expect(nameWrapper.read.isWrapped([
                namehash('eth'),
                labelhash('abcdefghijklmnop'),
            ])).resolves.toBe(false);
        });
        it('identifies an unregistered tld as unwrapped', async () => {
            const { nameWrapper } = await loadFixture();
            await expect(nameWrapper.read.isWrapped([
                zeroHash,
                labelhash('abc'),
            ])).resolves.toBe(false);
        });
        it('identifies a wrapped subname', async () => {
            const { nameWrapper, actions, accounts } = await loadFixture();
            await actions.setSubnodeOwner.onNameWrapper({
                parentName: name,
                label: sublabel,
                owner: accounts[0].address,
                fuses: 0,
                expiry: 0n,
            });
            await expect(nameWrapper.read.isWrapped([
                namehash(name),
                labelhash(sublabel),
            ])).resolves.toBe(true);
        });
        it('identifies an expired wrapped subname with PCC burnt as unwrapped', async () => {
            const { nameWrapper, actions, accounts, testClient, parentExpiry } = await loadFixture();
            await actions.setSubnodeOwner.onNameWrapper({
                parentName: name,
                label: sublabel,
                owner: accounts[0].address,
                fuses: PARENT_CANNOT_CONTROL,
                expiry: parentExpiry + 100n,
            });
            await expectOwnerOf(subname).on(nameWrapper).toBe(accounts[0]);
            await testClient.increaseTime({
                seconds: Number(DAY + GRACE_PERIOD + 101n),
            });
            await testClient.mine({ blocks: 1 });
            await expectOwnerOf(subname).on(nameWrapper).toBe(zeroAccount);
            await expect(nameWrapper.read.isWrapped([
                namehash(name),
                labelhash(sublabel),
            ])).resolves.toBe(false);
        });
    });
};
