import {
  AgentCardSchema,
  VaultfireExtensionDataSchema,
  CHAIN_CONFIGS,
  SUPPORTED_CHAINS,
  STREET_CRED_TIERS,
  getStreetCredTier,
  type AgentCard,
  type VaultfireExtensionData,
} from '../src/types';

describe('AgentCard Schema Validation', () => {
  const validCard: AgentCard = {
    name: 'Test Agent',
    url: 'https://agent.example.com',
    provider: { organization: 'Acme Corp', url: 'https://acme.com' },
    version: '1.0.0',
    capabilities: {
      streaming: true,
      pushNotifications: false,
    },
    skills: [
      {
        id: 'task-runner',
        name: 'Task Runner',
        description: 'Runs tasks',
        tags: ['automation'],
        examples: ['Run a script'],
        inputModes: ['text/plain'],
        outputModes: ['text/plain'],
      },
    ],
  };

  it('validates a valid Agent Card', () => {
    const result = AgentCardSchema.safeParse(validCard);
    expect(result.success).toBe(true);
  });

  it('requires name field', () => {
    const { name: _, ...noName } = validCard;
    const result = AgentCardSchema.safeParse(noName);
    expect(result.success).toBe(false);
  });

  it('requires url field', () => {
    const { url: _, ...noUrl } = validCard;
    const result = AgentCardSchema.safeParse(noUrl);
    expect(result.success).toBe(false);
  });

  it('validates url format', () => {
    const result = AgentCardSchema.safeParse({ ...validCard, url: 'not-a-url' });
    expect(result.success).toBe(false);
  });

  it('allows optional fields to be missing', () => {
    const minimal = { name: 'Minimal Agent', url: 'https://minimal.example.com' };
    const result = AgentCardSchema.safeParse(minimal);
    expect(result.success).toBe(true);
  });

  it('validates capabilities sub-fields', () => {
    const result = AgentCardSchema.safeParse({
      ...validCard,
      capabilities: { streaming: 'yes' }, // should be boolean
    });
    expect(result.success).toBe(false);
  });

  it('validates skills array', () => {
    const result = AgentCardSchema.safeParse({
      ...validCard,
      skills: [{ id: 'skill1', name: 'Skill 1' }],
    });
    expect(result.success).toBe(true);
  });
});

describe('VaultfireExtensionData Schema Validation', () => {
  const validExtension: VaultfireExtensionData = {
    chain: 'base',
    address: '0xfA15Ee28939B222B0448261A22156070f0A7813C',
    streetCred: { score: 55, tier: 'Gold', maxPossible: 95 },
    bonds: { total: 3, active: 2 },
    reputation: { averageRating: 4.2, totalFeedbacks: 5 },
    identity: { registered: true, active: true, agentType: 'autonomous' },
    verifiedAt: new Date().toISOString(),
  };

  it('validates a complete extension object', () => {
    const result = VaultfireExtensionDataSchema.safeParse(validExtension);
    expect(result.success).toBe(true);
  });

  it('rejects invalid chain', () => {
    const result = VaultfireExtensionDataSchema.safeParse({
      ...validExtension,
      chain: 'unsupported-chain',
    });
    expect(result.success).toBe(false);
  });

  it('rejects invalid Ethereum address', () => {
    const result = VaultfireExtensionDataSchema.safeParse({
      ...validExtension,
      address: 'not-an-address',
    });
    expect(result.success).toBe(false);
  });

  it('rejects score > 95', () => {
    const result = VaultfireExtensionDataSchema.safeParse({
      ...validExtension,
      streetCred: { score: 100, tier: 'Diamond', maxPossible: 95 },
    });
    expect(result.success).toBe(false);
  });

  it('rejects non-ISO timestamp', () => {
    const result = VaultfireExtensionDataSchema.safeParse({
      ...validExtension,
      verifiedAt: '2024-01-01',
    });
    expect(result.success).toBe(false);
  });

  it('rejects averageRating > 5', () => {
    const result = VaultfireExtensionDataSchema.safeParse({
      ...validExtension,
      reputation: { averageRating: 5.5, totalFeedbacks: 10 },
    });
    expect(result.success).toBe(false);
  });

  it('accepts all supported chains', () => {
    for (const chain of ['base', 'avalanche', 'arbitrum', 'polygon'] as const) {
      const result = VaultfireExtensionDataSchema.safeParse({ ...validExtension, chain });
      expect(result.success).toBe(true);
    }
  });
});

describe('CHAIN_CONFIGS', () => {
  it('has all supported chains', () => {
    for (const chain of SUPPORTED_CHAINS) {
      expect(CHAIN_CONFIGS[chain]).toBeDefined();
    }
  });

  it('has correct chain IDs', () => {
    expect(CHAIN_CONFIGS.base.chainId).toBe(8453);
    expect(CHAIN_CONFIGS.avalanche.chainId).toBe(43114);
    expect(CHAIN_CONFIGS.arbitrum.chainId).toBe(42161);
    expect(CHAIN_CONFIGS.polygon.chainId).toBe(137);
  });

  it('has valid RPC URLs', () => {
    for (const chain of SUPPORTED_CHAINS) {
      expect(CHAIN_CONFIGS[chain].rpcUrl).toMatch(/^https:\/\//);
    }
  });

  it('has all contract addresses for each chain', () => {
    for (const chain of SUPPORTED_CHAINS) {
      const contracts = CHAIN_CONFIGS[chain].contracts;
      expect(contracts.identity).toMatch(/^0x[0-9a-fA-F]{40}$/);
      expect(contracts.partnership).toMatch(/^0x[0-9a-fA-F]{40}$/);
      expect(contracts.reputation).toMatch(/^0x[0-9a-fA-F]{40}$/);
      expect(contracts.bridge).toMatch(/^0x[0-9a-fA-F]{40}$/);
    }
  });

  it('has correct Base contract addresses (production V2)', () => {
    expect(CHAIN_CONFIGS.base.contracts.identity).toBe(
      '0xa7BD20bf5De63df949cA5Be2F20835978eCba81A'
    );
    expect(CHAIN_CONFIGS.base.contracts.partnership).toBe(
      '0x01C479F0c039fEC40c0Cf1c5C921bab457d57441'
    );
    expect(CHAIN_CONFIGS.base.contracts.reputation).toBe(
      '0x98afd1440B2238D73c1394720277a6d031fCbbD0'
    );
    expect(CHAIN_CONFIGS.base.contracts.bridge).toBe(
      '0x62edf0cBc8Fa3d98B6A07197DFE9cb1c128a7eC7'
    );
  });

  it('has correct Avalanche contract addresses (production V2)', () => {
    expect(CHAIN_CONFIGS.avalanche.contracts.identity).toBe(
      '0x7448057C95Fb8a8B974a566cdcc9Cd042166A3f8'
    );
    expect(CHAIN_CONFIGS.avalanche.contracts.bridge).toBe(
      '0x1762e484A48558Ea5Cd056ac2CDf43FBbA52ba58'
    );
  });
});

describe('Street Cred Tiers', () => {
  it('has correct tier boundaries', () => {
    expect(STREET_CRED_TIERS.DIAMOND.min).toBe(80);
    expect(STREET_CRED_TIERS.PLATINUM.min).toBe(65);
    expect(STREET_CRED_TIERS.GOLD.min).toBe(50);
    expect(STREET_CRED_TIERS.SILVER.min).toBe(35);
    expect(STREET_CRED_TIERS.BRONZE.min).toBe(20);
    expect(STREET_CRED_TIERS.NEWCOMER.min).toBe(0);
  });

  it('getStreetCredTier returns correct tier for each range', () => {
    expect(getStreetCredTier(0)).toBe('Newcomer');
    expect(getStreetCredTier(19)).toBe('Newcomer');
    expect(getStreetCredTier(20)).toBe('Bronze');
    expect(getStreetCredTier(34)).toBe('Bronze');
    expect(getStreetCredTier(35)).toBe('Silver');
    expect(getStreetCredTier(49)).toBe('Silver');
    expect(getStreetCredTier(50)).toBe('Gold');
    expect(getStreetCredTier(64)).toBe('Gold');
    expect(getStreetCredTier(65)).toBe('Platinum');
    expect(getStreetCredTier(79)).toBe('Platinum');
    expect(getStreetCredTier(80)).toBe('Diamond');
    expect(getStreetCredTier(95)).toBe('Diamond');
  });
});
