import { shouldSupportInterfaces } from '@ensdomains/hardhat-chai-matchers-viem/behaviour';
import hre from 'hardhat';
import { deployDefaultReverseFixture } from '../fixtures/deployDefaultReverseFixture.js';
import { dnsEncodeName } from '../fixtures/dnsEncodeName.js';
import { chainFromCoinType, COIN_TYPE_DEFAULT, COIN_TYPE_ETH, getReverseName, isEVMCoinType, shortCoin, } from '../fixtures/ensip19.js';
import { makeResolutions } from '../utils/resolutions.js';
const testName = 'test.eth';
const coinTypes = [COIN_TYPE_ETH, COIN_TYPE_DEFAULT, 0n, 1n];
const connection = await hre.network.connect();
const loadFixture = async () => connection.networkHelpers.loadFixture(fixture);
async function fixture() {
    const F = await deployDefaultReverseFixture(connection);
    await F.defaultReverseRegistrar.write.setName([testName]);
    return F;
}
describe('DefaultReverseResolver', () => {
    shouldSupportInterfaces({
        contract: () => loadFixture().then((F) => F.defaultReverseResolver),
        interfaces: ['IERC165', 'IExtendedResolver', 'INameReverser', 'IERC7996'],
    });
    it('coinType()', async () => {
        const F = await loadFixture();
        await expect(F.defaultReverseResolver.read.coinType()).resolves.toStrictEqual(COIN_TYPE_DEFAULT);
    });
    it('chainId()', async () => {
        const F = await loadFixture();
        await expect(F.defaultReverseResolver.read.chainId()).resolves.toStrictEqual(chainFromCoinType(COIN_TYPE_DEFAULT));
    });
    describe('resolve()', () => {
        it('unsupported profile', async () => {
            const F = await loadFixture();
            const kp = {
                name: getReverseName(F.owner),
                texts: [{ key: 'dne', value: 'abc' }],
            };
            const [res] = makeResolutions(kp);
            await expect(F.defaultReverseResolver.read.resolve([
                dnsEncodeName(kp.name),
                res.call,
            ])).toBeRevertedWithCustomError('UnsupportedResolverProfile');
            // .withArgs(slice(res.call, 0, 4))
        });
        it('addr("default.reverse") = registrar', async () => {
            const F = await loadFixture();
            const kp = {
                name: F.defaultReverseNamespace,
                addresses: [
                    {
                        coinType: COIN_TYPE_DEFAULT,
                        value: F.defaultReverseRegistrar.address,
                    },
                    { coinType: COIN_TYPE_DEFAULT + 1n, value: '0x' },
                ],
            };
            for (const res of makeResolutions(kp)) {
                res.expect(await F.defaultReverseResolver.read.resolve([
                    dnsEncodeName(kp.name),
                    res.call,
                ]));
            }
        });
        for (const coinType of coinTypes) {
            it(shortCoin(coinType), async () => {
                const F = await loadFixture();
                const kp = {
                    name: getReverseName(F.owner, coinType),
                    primary: { value: testName },
                };
                const [res] = makeResolutions(kp);
                if (isEVMCoinType(coinType)) {
                    res.expect(await F.defaultReverseResolver.read.resolve([
                        dnsEncodeName(kp.name),
                        res.call,
                    ]));
                }
                else {
                    await expect(F.defaultReverseResolver.read.resolve([
                        dnsEncodeName(kp.name),
                        res.call,
                    ])).toBeRevertedWithCustomError('UnreachableName');
                    // .withArgs(dnsEncodeName(kp.name))
                }
            });
        }
    });
    describe('namespace edge cases', () => {
        for (const namespace of [
            '3c.reverse', // coinType(60)
            '03c.reverse', // coinType(60)
            '000000000000000000000000000000000000000000000000000000000000003c.reverse', // coinType(60)
            '80000000.reverse', // default
            '80000001.reverse', // chain(1)
        ]) {
            it(namespace, async () => {
                const F = await loadFixture();
                const kp = {
                    name: `${F.owner.slice(2).toLowerCase()}.${namespace}`,
                    primary: { value: testName },
                };
                const [res] = makeResolutions(kp);
                res.expect(await F.defaultReverseResolver.read.resolve([
                    dnsEncodeName(kp.name),
                    res.call,
                ]));
            });
        }
    });
    describe('resolveNames()', () => {
        it('empty', async () => {
            const F = await loadFixture();
            await expect(F.defaultReverseResolver.read.resolveNames([[]])).resolves.toStrictEqual([]);
        });
        it('multiple + 1 unset', async () => {
            const F = await loadFixture();
            const wallets = await connection.viem.getWalletClients();
            for (const w of wallets) {
                await F.defaultReverseRegistrar.write.setName([w.uid], {
                    account: w.account,
                });
            }
            await expect(F.defaultReverseResolver.read.resolveNames([
                [
                    ...wallets.map((x) => x.account.address),
                    F.defaultReverseRegistrar.address,
                ],
            ])).resolves.toStrictEqual([...wallets.map((x) => x.uid), '']);
        });
    });
});
