import { beforeEach, describe, expect, it, vi } from 'vitest'

import { callSimpleReadMethod, contractsApi } from './contracts'

describe('contractsApi', () => {
  beforeEach(() => {
    vi.restoreAllMocks()
  })

  it('normalizes contract profile metadata safely', async () => {
    vi.stubGlobal(
      'fetch',
      vi
        .fn()
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({
            has_custom_methods_read: true,
            has_custom_methods_write: false,
            proxy_type: 'eip1967',
            is_self_destructed: false,
            implementations: [{ address: '0ximpl1' }, '0ximpl2'],
            creation_bytecode: '0x' + 'a'.repeat(120),
            deployed_bytecode: '0x' + 'b'.repeat(120),
          }),
        })
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({
            status: '1',
            message: 'OK',
            result: '[{"type":"function","name":"symbol","stateMutability":"view","inputs":[],"outputs":[{"type":"string"}]}]',
          }),
        })
        .mockResolvedValueOnce({
          ok: true,
          json: async () => ({
            status: '1',
            message: 'OK',
            result: [
              {
                ContractName: 'MockToken',
                CompilerVersion: 'v0.8.24+commit',
                OptimizationUsed: '1',
                Runs: '200',
                EVMVersion: 'paris',
                LicenseType: 'MIT',
                ConstructorArguments: '0x' + 'c'.repeat(120),
                SourceCode: 'contract MockToken {}',
              },
            ],
          }),
        }),
    )

    const result = await contractsApi.getProfileSafe('0xcontract')

    expect(result.ok).toBe(true)
    expect(result.data?.has_custom_methods_read).toBe(true)
    expect(result.data?.proxy_type).toBe('eip1967')
    expect(result.data?.implementations).toEqual(['0ximpl1', '0ximpl2'])
    expect(result.data?.creation_bytecode?.endsWith('...')).toBe(true)
    expect(result.data?.source_verified).toBe(true)
    expect(result.data?.abi_available).toBe(true)
    expect(result.data?.contract_name).toBe('MockToken')
    expect(result.data?.optimization_enabled).toBe(true)
    expect(result.data?.optimization_runs).toBe(200)
    expect(result.data?.constructor_arguments?.endsWith('...')).toBe(true)
    expect(result.data?.abi).toContain('"symbol"')
    expect(result.data?.read_methods.map((method) => method.signature)).toContain('symbol()')
  })

  it('calls a simple zero-arg read method through public RPC', async () => {
    vi.stubGlobal(
      'fetch',
      vi.fn().mockResolvedValue({
        ok: true,
        json: async () => ({
          result:
            '0x' +
            '0000000000000000000000000000000000000000000000000000000000000020' +
            '0000000000000000000000000000000000000000000000000000000000000004' +
            '5445535400000000000000000000000000000000000000000000000000000000',
        }),
      }),
    )

    const value = await callSimpleReadMethod('0xcontract', {
      name: 'name',
      signature: 'name()',
      stateMutability: 'view',
      inputs: [],
      outputs: [{ name: '', type: 'string' }],
    })

    expect(value).toBe('TEST')
  })
})
