/**
 * WalletAdapter — Chain-parameterized abstraction over Safe/EOA/UP wallets.
 *
 * Provides a unified interface regardless of the underlying wallet backing type
 * (Gnosis Safe, raw EOA, or LUKSO Universal Profile).
 */

import type { SafeWalletEntry } from './wallet-store';

export type WalletBackingType = 'safe' | 'eoa' | 'up';

export interface WalletInfo {
  /** Effective sending address (Safe address, EOA, or UP) */
  address: string;
  /** Underlying EOA address (from passkey-derived key) */
  signerAddress: string;
  /** EVM chain ID */
  chainId: number;
  /** Wallet backing type */
  type: WalletBackingType;
  /** User-assigned label */
  label: string;
  /** Whether a Universal Profile is associated */
  hasUniversalProfile: boolean;
  /** UP address if one is associated */
  upAddress?: string;
}

interface WalletAdapterParams {
  address: string;
  signerAddress: string;
  chainId: number;
  type: WalletBackingType;
  label: string;
  upAddress?: string;
}

export class WalletAdapter {
  private readonly params: WalletAdapterParams;

  private constructor(params: WalletAdapterParams) {
    this.params = params;
  }

  /**
   * Create a WalletAdapter from an existing Gnosis Safe entry.
   */
  static fromSafe(entry: SafeWalletEntry, eoaAddress: string): WalletAdapter {
    return new WalletAdapter({
      address: entry.safeAddress,
      signerAddress: eoaAddress,
      chainId: entry.chainId,
      type: 'safe',
      label: entry.label,
    });
  }

  /**
   * Create a WalletAdapter for a raw EOA (passkey-derived secp256k1 key).
   */
  static fromEOA(eoaAddress: string, chainId: number, label?: string): WalletAdapter {
    return new WalletAdapter({
      address: eoaAddress,
      signerAddress: eoaAddress,
      chainId,
      type: 'eoa',
      label: label ?? 'EOA Wallet',
    });
  }

  /**
   * Create a WalletAdapter for a LUKSO Universal Profile.
   */
  static fromUP(upAddress: string, controllerEOA: string, chainId: number, label?: string): WalletAdapter {
    return new WalletAdapter({
      address: upAddress,
      signerAddress: controllerEOA,
      chainId,
      type: 'up',
      label: label ?? 'Universal Profile',
      upAddress,
    });
  }

  /**
   * Returns a new WalletAdapter with a Universal Profile associated.
   * The original instance is not mutated.
   */
  withUniversalProfile(upAddress: string): WalletAdapter {
    return new WalletAdapter({
      ...this.params,
      upAddress,
    });
  }

  /**
   * Get wallet info, optionally overriding the chain ID.
   */
  getInfo(chainId?: number): WalletInfo {
    const effectiveChainId = chainId ?? this.params.chainId;
    return {
      address: this.params.address,
      signerAddress: this.params.signerAddress,
      chainId: effectiveChainId,
      type: this.params.type,
      label: this.params.label,
      hasUniversalProfile: !!this.params.upAddress,
      ...(this.params.upAddress && { upAddress: this.params.upAddress }),
    };
  }

  /**
   * Serialize to a plain object (no sensitive data).
   */
  toJSON(): Record<string, unknown> {
    return {
      address: this.params.address,
      signerAddress: this.params.signerAddress,
      chainId: this.params.chainId,
      type: this.params.type,
      label: this.params.label,
      upAddress: this.params.upAddress ?? null,
    };
  }
}
