import { z } from 'zod';

// ─── Chain Types ────────────────────────────────────────────────────────────

export type SupportedChain = 'base' | 'avalanche' | 'arbitrum' | 'polygon';

export const SUPPORTED_CHAINS: SupportedChain[] = ['base', 'avalanche', 'arbitrum', 'polygon'];

// ─── Chain Configuration ─────────────────────────────────────────────────────

export interface ChainConfig {
  chainId: number;
  name: string;
  rpcUrl: string;
  contracts: {
    identity: string;
    partnership: string;
    accountability: string;
    reputation: string;
    bridge: string;
  };
  explorer: string;
}

// Production addresses verified on-chain 2026-04-29
// Source: https://theloopbreaker.com/api/contracts (134 contracts live across 4 chains)
export const CHAIN_CONFIGS: Record<SupportedChain, ChainConfig> = {
  base: {
    chainId: 8453,
    name: 'Base',
    rpcUrl: 'https://mainnet.base.org',
    contracts: {
      identity: '0xa7BD20bf5De63df949cA5Be2F20835978eCba81A',
      partnership: '0x01C479F0c039fEC40c0Cf1c5C921bab457d57441',
      accountability: '0x6750D28865434344e04e1D0a6044394b726C3dfE',
      reputation: '0x98afd1440B2238D73c1394720277a6d031fCbbD0',
      bridge: '0x62edf0cBc8Fa3d98B6A07197DFE9cb1c128a7eC7',
    },
    explorer: 'https://basescan.org',
  },
  avalanche: {
    chainId: 43114,
    name: 'Avalanche',
    rpcUrl: 'https://api.avax.network/ext/bc/C/rpc',
    contracts: {
      identity: '0x7448057C95Fb8a8B974a566cdcc9Cd042166A3f8',
      partnership: '0xDC8447c66fE9D9c7D54607A98346A15324b7985D',
      accountability: '0x376831fB2457E34559891c32bEb61c442053C066',
      reputation: '0x5DB1B4b412b80d03819395794fCcF5A73BF30656',
      bridge: '0x1762e484A48558Ea5Cd056ac2CDf43FBbA52ba58',
    },
    explorer: 'https://snowtrace.io',
  },
  arbitrum: {
    chainId: 42161,
    name: 'Arbitrum',
    rpcUrl: 'https://arbitrum-one.publicnode.com',
    contracts: {
      identity: '0x83dd216449B3F0574E39043ECFE275946fa492e9',
      partnership: '0xdB54B8925664816187646174bdBb6Ac658A55a5F',
      accountability: '0xef3A944f4d7bb376699C83A29d7Cb42C90D9B6F0',
      reputation: '0x8B8Ba34F8AAB800F0Ba8391fb1388c6EFb911F92',
      bridge: '0x7b9293B05Bd0fcb7458d06A364078761B8E8848e',
    },
    explorer: 'https://arbiscan.io',
  },
  polygon: {
    chainId: 137,
    name: 'Polygon',
    rpcUrl: 'https://polygon-bor-rpc.publicnode.com',
    contracts: {
      identity: '0xD9bF6D92a1D9ee44a48c38481c046a819CBdf2ba',
      partnership: '0x83dd216449B3F0574E39043ECFE275946fa492e9',
      accountability: '0xdB54B8925664816187646174bdBb6Ac658A55a5F',
      reputation: '0x54e00081978eE2C8d9Ada8e9975B0Bb543D06A55',
      bridge: '0x7b9293B05Bd0fcb7458d06A364078761B8E8848e',
    },
    explorer: 'https://polygonscan.com',
  },
};

// ─── Contract ABIs ────────────────────────────────────────────────────────────

export const IDENTITY_ABI = [
  'function registerAgent(string agentURI, string agentType, bytes32 capabilitiesHash)',
  'function getAgent(address) view returns (string agentURI, bool active, string agentType, uint256 registeredAt)',
  'function isAgentActive(address) view returns (bool)',
  'function getTotalAgents() view returns (uint256)',
  'function discoverAgentsByCapability(bytes32) view returns (address[])',
] as const;

export const PARTNERSHIP_ABI = [
  'function createBond(address aiAgent, string partnershipType) payable returns (uint256)',
  'function getBond(uint256 bondId) view returns (tuple(uint256 bondId, address human, address aiAgent, string partnershipType, uint256 stakeAmount, uint256 createdAt, uint256 distributionRequestedAt, bool distributionPending, bool active))',
  'function nextBondId() view returns (uint256)',
  'function getBondsByParticipant(address) view returns (uint256[])',
] as const;

export const ACCOUNTABILITY_ABI = [
  'function createBond(address aiAgent, string bondType) payable returns (uint256)',
  'function getBond(uint256 bondId) view returns (tuple(uint256 bondId, address human, address aiAgent, string bondType, uint256 stakeAmount, uint256 createdAt, uint256 distributionRequestedAt, bool distributionPending, bool active))',
  'function nextBondId() view returns (uint256)',
  'function getBondsByParticipant(address) view returns (uint256[])',
  'function slashBond(uint256 bondId, string reason)',
] as const;

export const REPUTATION_ABI = [
  'function getReputation(address) view returns (uint256 averageRating, uint256 totalFeedbacks, uint256 verifiedFeedbacks, uint256 lastUpdated)',
] as const;

export const BRIDGE_ABI = [
  'function isAgentRecognized(address) view returns (bool)',
  'function getSyncedAgentCount() view returns (uint256)',
] as const;

// ─── Street Cred Tiers ────────────────────────────────────────────────────────

export const STREET_CRED_TIERS = {
  DIAMOND: { min: 80, max: 95, label: 'Diamond' },
  PLATINUM: { min: 65, max: 79, label: 'Platinum' },
  GOLD: { min: 50, max: 64, label: 'Gold' },
  SILVER: { min: 35, max: 49, label: 'Silver' },
  BRONZE: { min: 20, max: 34, label: 'Bronze' },
  NEWCOMER: { min: 0, max: 19, label: 'Newcomer' },
} as const;

export type StreetCredTier = keyof typeof STREET_CRED_TIERS;

export function getStreetCredTier(score: number): string {
  for (const [, tier] of Object.entries(STREET_CRED_TIERS)) {
    if (score >= tier.min && score <= tier.max) {
      return tier.label;
    }
  }
  return 'Newcomer';
}

// ─── A2A Agent Card Types (Google Spec) ──────────────────────────────────────

export const AgentCapabilitiesSchema = z.object({
  streaming: z.boolean().optional(),
  pushNotifications: z.boolean().optional(),
  stateTransitionHistory: z.boolean().optional(),
});

export type AgentCapabilities = z.infer<typeof AgentCapabilitiesSchema>;

export const AgentSkillSchema = z.object({
  id: z.string(),
  name: z.string(),
  description: z.string().optional(),
  tags: z.array(z.string()).optional(),
  examples: z.array(z.string()).optional(),
  inputModes: z.array(z.string()).optional(),
  outputModes: z.array(z.string()).optional(),
});

export type AgentSkill = z.infer<typeof AgentSkillSchema>;

export const AgentProviderSchema = z.object({
  organization: z.string(),
  url: z.string().url().optional(),
});

export type AgentProvider = z.infer<typeof AgentProviderSchema>;

export const AgentCardSchema = z.object({
  name: z.string(),
  description: z.string().optional(),
  url: z.string().url(),
  provider: AgentProviderSchema.optional(),
  version: z.string().optional(),
  documentationUrl: z.string().url().optional(),
  capabilities: AgentCapabilitiesSchema.optional(),
  securitySchemes: z.record(z.unknown()).optional(),
  security: z.array(z.record(z.array(z.string()))).optional(),
  defaultInputModes: z.array(z.string()).optional(),
  defaultOutputModes: z.array(z.string()).optional(),
  skills: z.array(AgentSkillSchema).optional(),
  supportsAuthenticatedExtendedCard: z.boolean().optional(),
});

export type AgentCard = z.infer<typeof AgentCardSchema>;

// ─── Vaultfire Extension Types ────────────────────────────────────────────────

export const VaultfireStreetCredSchema = z.object({
  score: z.number().min(0).max(95),
  tier: z.string(),
  maxPossible: z.literal(95),
});

export type VaultfireStreetCred = z.infer<typeof VaultfireStreetCredSchema>;

export const VaultfireBondsSchema = z.object({
  total: z.number().int().nonnegative(),
  active: z.number().int().nonnegative(),
});

export type VaultfireBonds = z.infer<typeof VaultfireBondsSchema>;

export const VaultfireReputationSchema = z.object({
  averageRating: z.number().min(0).max(5),
  totalFeedbacks: z.number().int().nonnegative(),
});

export type VaultfireReputation = z.infer<typeof VaultfireReputationSchema>;

export const VaultfireIdentitySchema = z.object({
  registered: z.boolean(),
  active: z.boolean(),
  agentType: z.string(),
});

export type VaultfireIdentity = z.infer<typeof VaultfireIdentitySchema>;

export const VaultfireExtensionDataSchema = z.object({
  chain: z.enum(['base', 'avalanche', 'arbitrum', 'polygon']),
  address: z.string().regex(/^0x[0-9a-fA-F]{40}$/, 'Invalid EVM address'),
  streetCred: VaultfireStreetCredSchema,
  bonds: VaultfireBondsSchema,
  reputation: VaultfireReputationSchema,
  identity: VaultfireIdentitySchema,
  verifiedAt: z.string().datetime(),
});

export type VaultfireExtensionData = z.infer<typeof VaultfireExtensionDataSchema>;

// The enriched Agent Card has all AgentCard fields plus x-vaultfire
export type EnrichedAgentCard = AgentCard & {
  'x-vaultfire': VaultfireExtensionData;
};

// ─── Raw on-chain data structures ─────────────────────────────────────────────

export interface OnChainAgentData {
  identity: {
    agentURI: string;
    active: boolean;
    agentType: string;
    registeredAt: bigint;
  };
  bonds: {
    total: number;
    active: number;
  };
  reputation: {
    averageRating: bigint;
    totalFeedbacks: bigint;
    verifiedFeedbacks: bigint;
    lastUpdated: bigint;
  };
  isRecognized: boolean;
}

// ─── Verification Result ──────────────────────────────────────────────────────

export interface VerificationResult {
  trusted: boolean;
  streetCred: VaultfireStreetCred;
  bonds: VaultfireBonds;
  reputation: VaultfireReputation;
  identity: VaultfireIdentity;
  reason: string;
  chain: SupportedChain;
  address: string;
  verifiedAt: string;
}

// ─── Discovery Types ──────────────────────────────────────────────────────────

export interface DiscoverOptions {
  chain: SupportedChain;
  minStreetCred?: number;
  minBonds?: number;
  requireActive?: boolean;
  agentType?: string;
  limit?: number;
}

export interface DiscoveredAgent {
  address: string;
  chain: SupportedChain;
  agentURI: string;
  agentType: string;
  streetCred: VaultfireStreetCred;
  bonds: VaultfireBonds;
  reputation: VaultfireReputation;
  active: boolean;
}

// ─── Enrich Options ───────────────────────────────────────────────────────────

export interface EnrichOptions {
  agentCard: AgentCard;
  chain: SupportedChain;
  agentAddress: string;
}
