/**
 * Vaultfire Name Service (VNS) — Resolver
 *
 * High-level resolution utilities that wrap the vns-client primitives.
 * Use these when you need clean, composable resolution without dealing
 * with the low-level RPC and ABI encoding details.
 *
 * Key functions:
 * - resolve(name)           Resolve a .vns name to its full profile
 * - reverseResolve(address) Get the .vns name for a wallet address
 * - resolveToAddress(name)  Resolve a name directly to a wallet address
 * - resolveToPayment(name)  Resolve a name to its payment address
 * - batchResolve(names[])   Resolve multiple names in parallel
 * - isValidName(name)       Quick validation check
 */

import type { VNSProfile, VNSAvailability } from './types.js';

import {
  resolveVNSName,
  reverseResolveVNS,
  resolvePaymentAddress,
  checkVNSAvailability,
  validateVNSName,
  formatVNSName,
  stripVNSSuffix,
  getProfileByAddress,
} from './vns-client.js';

export type { VNSProfile, VNSAvailability };

// ── Resolver Class ─────────────────────────────────────────────────────────────

/**
 * VNSResolver provides a clean, stateless API for name and address resolution.
 *
 * @example
 * ```typescript
 * const resolver = new VNSResolver();
 *
 * // Resolve name → profile
 * const profile = await resolver.resolve('ghostkey316');
 * console.log(profile?.address); // "0x..."
 *
 * // Reverse resolve address → name
 * const name = await resolver.reverseResolve('0x1234...');
 * console.log(name); // "ghostkey316.vns"
 * ```
 */
export class VNSResolver {
  /**
   * Resolve a .vns name to its full profile.
   *
   * Accepts names with or without the .vns suffix.
   * Returns null if the name is not registered.
   *
   * @example
   * ```typescript
   * const profile = await resolver.resolve('ghostkey316.vns');
   * const profile2 = await resolver.resolve('ghostkey316'); // same result
   * ```
   */
  async resolve(name: string): Promise<VNSProfile | null> {
    const normalized = formatVNSName(name);
    return resolveVNSName(normalized);
  }

  /**
   * Reverse resolve a wallet address to its .vns name.
   *
   * Returns the full .vns name (e.g. "ghostkey316.vns") or null
   * if the address has no registered name.
   *
   * @example
   * ```typescript
   * const name = await resolver.reverseResolve('0xfA15Ee28939B222B0448261A22156070f0A7813C');
   * // → "vaultfire-sentinel.vns"
   * ```
   */
  async reverseResolve(address: string): Promise<string | null> {
    return reverseResolveVNS(address);
  }

  /**
   * Resolve a .vns name or raw address directly to a wallet address.
   *
   * Returns the address string or null if resolution fails.
   *
   * @example
   * ```typescript
   * const addr = await resolver.resolveToAddress('ghostkey316');
   * // → "0x..."
   * ```
   */
  async resolveToAddress(nameOrAddress: string): Promise<string | null> {
    // Raw address — return as-is
    if (/^0x[a-fA-F0-9]{40}$/.test(nameOrAddress)) {
      return nameOrAddress;
    }

    const profile = await resolveVNSName(formatVNSName(nameOrAddress));
    return profile?.address ?? null;
  }

  /**
   * Resolve a .vns name or raw address to its payment address.
   *
   * The payment address may differ from the identity address if
   * the user has set a custom payment address via setPaymentPreferences().
   *
   * Returns { address, vnsName?, vnsProfile? } or null.
   *
   * @example
   * ```typescript
   * const result = await resolver.resolveToPayment('vaultfire-sentinel');
   * // → { address: "0x...", vnsName: "vaultfire-sentinel.vns", vnsProfile: {...} }
   * ```
   */
  async resolveToPayment(nameOrAddress: string) {
    return resolvePaymentAddress(nameOrAddress);
  }

  /**
   * Get the full profile for a wallet address.
   *
   * Equivalent to getProfileByAddress() but available on the resolver instance.
   */
  async getProfileForAddress(address: string): Promise<VNSProfile | null> {
    return getProfileByAddress(address);
  }

  /**
   * Check whether a name is available to register.
   *
   * @example
   * ```typescript
   * const avail = await resolver.checkAvailability('my-new-agent');
   * if (avail.available) {
   *   console.log('Name is free!');
   * } else {
   *   console.log(`Taken by ${avail.takenBy}`);
   * }
   * ```
   */
  async checkAvailability(name: string): Promise<VNSAvailability> {
    return checkVNSAvailability(name);
  }

  /**
   * Resolve multiple .vns names in parallel.
   *
   * Returns an array of profiles in the same order as the input names.
   * Unresolvable names produce null entries.
   *
   * @example
   * ```typescript
   * const profiles = await resolver.batchResolve([
   *   'ghostkey316',
   *   'vaultfire-sentinel',
   *   'embris-research',
   * ]);
   * ```
   */
  async batchResolve(names: string[]): Promise<(VNSProfile | null)[]> {
    return Promise.all(names.map(name => this.resolve(name)));
  }

  /**
   * Reverse-resolve multiple addresses in parallel.
   *
   * Returns an array of .vns names in the same order as the input addresses.
   * Addresses with no name produce null entries.
   */
  async batchReverseResolve(addresses: string[]): Promise<(string | null)[]> {
    return Promise.all(addresses.map(addr => this.reverseResolve(addr)));
  }

  /**
   * Check if a name string is valid (without querying the chain).
   * Returns true if the name passes all format rules.
   */
  isValidName(name: string): boolean {
    return validateVNSName(name).valid;
  }

  /**
   * Normalize a name to its canonical form.
   *
   * @example
   * ```typescript
   * resolver.normalize('GHOSTKEY316.VNS') // → 'ghostkey316.vns'
   * resolver.normalize('ghostkey316')     // → 'ghostkey316.vns'
   * ```
   */
  normalize(name: string): string {
    return formatVNSName(name);
  }

  /**
   * Strip the .vns suffix and normalize to lowercase.
   *
   * @example
   * ```typescript
   * resolver.strip('ghostkey316.vns') // → 'ghostkey316'
   * ```
   */
  strip(name: string): string {
    return stripVNSSuffix(name);
  }
}

// ── Singleton Resolver ─────────────────────────────────────────────────────────

/**
 * Default singleton VNSResolver instance.
 * Import and use directly for simple integrations.
 *
 * @example
 * ```typescript
 * import { resolver } from '@vaultfire/vns';
 *
 * const profile = await resolver.resolve('ghostkey316');
 * ```
 */
export const resolver = new VNSResolver();

// ── Standalone Resolver Functions ──────────────────────────────────────────────

/**
 * Resolve a .vns name to its full profile.
 * Standalone function equivalent to resolver.resolve().
 */
export async function resolve(name: string): Promise<VNSProfile | null> {
  return resolver.resolve(name);
}

/**
 * Reverse resolve an address to its .vns name.
 * Standalone function equivalent to resolver.reverseResolve().
 */
export async function reverseResolve(address: string): Promise<string | null> {
  return resolver.reverseResolve(address);
}

/**
 * Resolve a .vns name to its wallet address.
 * Returns null if the name is not registered.
 */
export async function resolveToAddress(nameOrAddress: string): Promise<string | null> {
  return resolver.resolveToAddress(nameOrAddress);
}

/**
 * Resolve a .vns name or address to its payment address.
 * Returns null if resolution fails.
 */
export async function resolveToPayment(nameOrAddress: string) {
  return resolver.resolveToPayment(nameOrAddress);
}

/**
 * Check if a name is available to register.
 */
export async function checkAvailability(name: string): Promise<VNSAvailability> {
  return resolver.checkAvailability(name);
}

/**
 * Resolve multiple .vns names in parallel.
 */
export async function batchResolve(names: string[]): Promise<(VNSProfile | null)[]> {
  return resolver.batchResolve(names);
}

/**
 * Quick validation check without hitting the chain.
 */
export function isValidName(name: string): boolean {
  return resolver.isValidName(name);
}
