/**
 * Client-side helpers for VaultfireStreetCred (ERC-5192 soulbound badge).
 *
 * Mirrors the SDK's getStreetCred / buildMintStreetCredTx but uses viem
 * directly so the mini-app stays consistent with the rest of its Wagmi/viem
 * setup.
 */

import { createPublicClient, http, encodeFunctionData, type Address, type Hex } from 'viem';
import { base } from 'viem/chains';

export const STREET_CRED_ADDRESS: Address =
  '0x5CfAB4B12718549e156D3642f9C63476aC4c2f99';

export const STREET_CRED_TIER_NAMES = [
  'None',
  'Bronze',
  'Silver',
  'Gold',
  'Platinum',
] as const;
export type StreetCredTier = (typeof STREET_CRED_TIER_NAMES)[number];

const STREET_CRED_ABI = [
  {
    type: 'function',
    name: 'computeScore',
    stateMutability: 'view',
    inputs: [{ name: 'agent', type: 'address' }],
    outputs: [
      { name: 'score', type: 'uint16' },
      { name: 'tier', type: 'uint8' },
      { name: 'registered', type: 'bool' },
      { name: 'hasBond', type: 'bool' },
      { name: 'bondActive', type: 'bool' },
      { name: 'bondCount', type: 'uint256' },
      { name: 'stakeWei', type: 'uint256' },
    ],
  },
  {
    type: 'function',
    name: 'hasBadge',
    stateMutability: 'view',
    inputs: [{ name: 'agent', type: 'address' }],
    outputs: [{ type: 'bool' }],
  },
  {
    type: 'function',
    name: 'mintFor',
    stateMutability: 'nonpayable',
    inputs: [{ name: 'agent', type: 'address' }],
    outputs: [{ name: 'tokenId', type: 'uint256' }],
  },
  {
    type: 'function',
    name: 'tokenURI',
    stateMutability: 'view',
    inputs: [{ name: 'tokenId', type: 'uint256' }],
    outputs: [{ type: 'string' }],
  },
] as const;

export interface StreetCredState {
  score: number;
  tier: number;
  tierName: StreetCredTier;
  registered: boolean;
  hasBond: boolean;
  bondActive: boolean;
  bondCount: number;
  stakeWei: bigint;
  hasBadge: boolean;
}

const client = createPublicClient({
  chain: base,
  transport: http('https://mainnet.base.org'),
});

export async function readStreetCred(agent: Address): Promise<StreetCredState> {
  const [computeRes, hasBadge] = await Promise.all([
    client.readContract({
      address: STREET_CRED_ADDRESS,
      abi: STREET_CRED_ABI,
      functionName: 'computeScore',
      args: [agent],
    }),
    client.readContract({
      address: STREET_CRED_ADDRESS,
      abi: STREET_CRED_ABI,
      functionName: 'hasBadge',
      args: [agent],
    }),
  ]);

  const [score, tier, registered, hasBond, bondActive, bondCount, stakeWei] =
    computeRes as readonly [number, number, boolean, boolean, boolean, bigint, bigint];

  return {
    score: Number(score),
    tier: Number(tier),
    tierName: STREET_CRED_TIER_NAMES[Number(tier)] ?? 'None',
    registered,
    hasBond,
    bondActive,
    bondCount: Number(bondCount),
    stakeWei,
    hasBadge: hasBadge as boolean,
  };
}

export async function readTokenURI(tokenId: bigint): Promise<string> {
  return (await client.readContract({
    address: STREET_CRED_ADDRESS,
    abi: STREET_CRED_ABI,
    functionName: 'tokenURI',
    args: [tokenId],
  })) as string;
}

export function encodeMintFor(agent: Address): Hex {
  return encodeFunctionData({
    abi: STREET_CRED_ABI,
    functionName: 'mintFor',
    args: [agent],
  });
}

export function tokenIdOf(agent: Address): bigint {
  return BigInt(agent.toLowerCase());
}

export function tierColor(tier: number): string {
  switch (tier) {
    case 4: return '#e5e4e2'; // platinum
    case 3: return '#d4af37'; // gold
    case 2: return '#c0c0c0'; // silver
    case 1: return '#cd7f32'; // bronze
    default: return '#444444';
  }
}
