import { describe, it, expect } from 'vitest'
import { AdoptionAggregator } from '../aggregator'
import { AdoptionSnapshot } from '../types'

describe('AdoptionAggregator', () => {
  const aggregator = new AdoptionAggregator()

  const createSnapshots = (count: number, withASPAPercent: number = 50): AdoptionSnapshot[] => {
    const snapshots: AdoptionSnapshot[] = []
    for (let i = 0; i < count; i++) {
      snapshots.push({
        asn: 10000 + i,
        hasASPA: Math.random() * 100 < withASPAPercent,
        providers: Math.random() < 0.5 ? [] : [100 + i % 3, 200 + i % 3],
        region: ['APNIC', 'RIPE', 'ARIN', 'LACNIC'][i % 4],
      })
    }
    return snapshots
  }

  describe('aggregate', () => {
    it('should calculate overall coverage correctly', () => {
      const snapshots = createSnapshots(100, 50)
      const result = aggregator.aggregate(snapshots)

      expect(result.overall.total).toBe(100)
      expect(result.overall.withASPA).toBeGreaterThan(0)
      expect(result.overall.withASPA).toBeLessThanOrEqual(100)
      expect(result.overall.coverage).toBeGreaterThanOrEqual(0)
      expect(result.overall.coverage).toBeLessThanOrEqual(100)
    })

    it('should aggregate by region', () => {
      const snapshots = createSnapshots(100)
      const result = aggregator.aggregate(snapshots, {
        includeRegions: true,
        includeIXPs: false,
      })

      expect(Array.isArray(result.regions)).toBe(true)
      expect(result.regions.length).toBeGreaterThan(0)

      for (const region of result.regions) {
        expect(region.region).toBeDefined()
        expect(region.totalASNs).toBeGreaterThan(0)
        expect(region.ASNsWithASPA).toBeGreaterThanOrEqual(0)
        expect(region.coveragePercentage).toBeGreaterThanOrEqual(0)
        expect(region.coveragePercentage).toBeLessThanOrEqual(100)
      }
    })

    it('should sort regions by coverage descending', () => {
      const snapshots = createSnapshots(100)
      const result = aggregator.aggregate(snapshots, { includeRegions: true, includeIXPs: false })

      for (let i = 0; i < result.regions.length - 1; i++) {
        expect(result.regions[i].coveragePercentage).toBeGreaterThanOrEqual(result.regions[i + 1].coveragePercentage)
      }
    })

    it('should handle 100% adoption', () => {
      const snapshots = createSnapshots(50, 100)
      const result = aggregator.aggregate(snapshots)

      expect(result.overall.coverage).toBe(100)
      expect(result.overall.withASPA).toBe(result.overall.total)
    })

    it('should handle 0% adoption', () => {
      const snapshots = createSnapshots(50, 0)
      const result = aggregator.aggregate(snapshots)

      expect(result.overall.coverage).toBe(0)
      expect(result.overall.withASPA).toBe(0)
    })

    it('should calculate coverage as percentage', () => {
      const snapshots = [
        { asn: 1, hasASPA: true, providers: [1, 2], region: 'RIPE' },
        { asn: 2, hasASPA: true, providers: [1], region: 'RIPE' },
        { asn: 3, hasASPA: false, providers: [], region: 'RIPE' },
        { asn: 4, hasASPA: false, providers: [], region: 'RIPE' },
      ]

      const result = aggregator.aggregate(snapshots)

      expect(result.overall.total).toBe(4)
      expect(result.overall.withASPA).toBe(2)
      expect(result.overall.coverage).toBe(50)
    })

    it('should not include disabled aggregations', () => {
      const snapshots = createSnapshots(100)
      const result = aggregator.aggregate(snapshots, {
        includeRegions: false,
        includeIXPs: false,
      })

      expect(result.regions.length).toBe(0)
      expect(result.ixps.length).toBe(0)
    })
  })

  describe('top networks in regions', () => {
    it('should return top networks sorted by provider count', () => {
      const snapshots = createSnapshots(50)
      const result = aggregator.aggregate(snapshots, { includeRegions: true, includeIXPs: false })

      for (const region of result.regions) {
        if (region.topNetworks.length > 1) {
          for (let i = 0; i < region.topNetworks.length - 1; i++) {
            expect(region.topNetworks[i].providers).toBeGreaterThanOrEqual(region.topNetworks[i + 1].providers)
          }
        }
      }
    })
  })
})
