import { describe, it, expect } from 'vitest';
import { estimateBandwidth } from '../utils';

describe('estimateBandwidth', () => {
  describe('Video streaming use cases', () => {
    it('should estimate bandwidth for video streaming with CDN', () => {
      const result = estimateBandwidth(100, 'video streaming platform');
      // Video streaming with CDN (92% cache) reduces origin traffic significantly
      expect(result.cdn_enabled).toBe(true);
      expect(result.cdn_cache_hit_rate).toBe(0.92);
      expect(result.gross_monthly_tb).toBeGreaterThan(6); // Gross traffic is very_heavy
      expect(result.origin_monthly_tb).toBeLessThan(result.gross_monthly_tb); // Origin is reduced
      expect(result.category).toBe('heavy'); // Origin traffic category
      expect(result.estimated_dau_min).toBeGreaterThan(0);
      expect(result.estimated_dau_max).toBeGreaterThan(result.estimated_dau_min);
    });

    it('should estimate very_heavy bandwidth without CDN', () => {
      const result = estimateBandwidth(100, 'video streaming platform', undefined, { enabled: false });
      // Without CDN, video streaming is very_heavy
      expect(result.cdn_enabled).toBe(false);
      expect(result.category).toBe('very_heavy');
      expect(result.monthly_tb).toBeGreaterThan(6);
      expect(result.gross_monthly_tb).toBe(result.origin_monthly_tb); // No CDN reduction
    });

    it('should estimate higher bandwidth for 4K streaming', () => {
      const hd = estimateBandwidth(100, 'HD video streaming');
      const fourK = estimateBandwidth(100, '4K UHD streaming');
      expect(fourK.gross_monthly_tb).toBeGreaterThan(hd.gross_monthly_tb);
    });
  });

  describe('CDN cache hit rate', () => {
    it('should apply use-case specific CDN cache hit rates', () => {
      const video = estimateBandwidth(100, 'video streaming');
      const blog = estimateBandwidth(100, 'personal blog');
      const api = estimateBandwidth(100, 'REST API');
      const gaming = estimateBandwidth(100, 'game server');

      expect(video.cdn_cache_hit_rate).toBe(0.92); // Video: high cache
      expect(blog.cdn_cache_hit_rate).toBe(0.90);  // Blog: high cache
      expect(api.cdn_cache_hit_rate).toBe(0.30);   // API: low cache
      expect(gaming.cdn_cache_hit_rate).toBe(0.20); // Gaming: very low cache
    });

    it('should allow CDN cache hit rate override', () => {
      const result = estimateBandwidth(100, 'video streaming', undefined, { cacheHitRate: 0.50 });
      expect(result.cdn_cache_hit_rate).toBe(0.50);
      expect(result.origin_monthly_tb).toBeCloseTo(result.gross_monthly_tb * 0.50, 1);
    });

    it('should calculate CDN savings correctly', () => {
      const withCdn = estimateBandwidth(100, 'video streaming');
      const withoutCdn = estimateBandwidth(100, 'video streaming', undefined, { enabled: false });

      // CDN should reduce origin traffic significantly
      expect(withCdn.origin_monthly_tb).toBeLessThan(withoutCdn.origin_monthly_tb);
      // Gross should be the same
      expect(withCdn.gross_monthly_tb).toBe(withoutCdn.gross_monthly_tb);
    });
  });

  describe('E-commerce use cases', () => {
    it('should estimate bandwidth for e-commerce', () => {
      const result = estimateBandwidth(500, 'e-commerce website');
      expect(result.category).toBeDefined();
      expect(result.monthly_gb).toBeGreaterThan(0);
      expect(result.description).toBeDefined();
    });

    it('should estimate bandwidth for shopping mall', () => {
      const result = estimateBandwidth(1000, '온라인 쇼핑몰');
      expect(result.category).toBeDefined();
      expect(result.monthly_tb).toBeGreaterThan(0);
    });
  });

  describe('Blog and static content', () => {
    it('should estimate light bandwidth for blog', () => {
      const result = estimateBandwidth(200, 'personal blog');
      expect(result.category).toBe('light');
      expect(result.monthly_tb).toBeLessThan(1);
    });

    it('should estimate light bandwidth for portfolio', () => {
      const result = estimateBandwidth(100, 'portfolio website');
      expect(result.category).toBe('light');
    });
  });

  describe('API and SaaS', () => {
    it('should estimate bandwidth for API service', () => {
      const result = estimateBandwidth(500, 'REST API backend');
      expect(result.category).toBeDefined();
      expect(result.monthly_gb).toBeGreaterThan(0);
    });

    it('should estimate bandwidth for SaaS application', () => {
      const result = estimateBandwidth(1000, 'SaaS application');
      expect(result.category).toBeDefined();
      expect(result.active_ratio).toBeGreaterThan(0);
    });
  });

  describe('Gaming use cases', () => {
    it('should estimate bandwidth for game server', () => {
      const result = estimateBandwidth(200, 'game server');
      expect(result.category).toBeDefined();
      expect(result.monthly_gb).toBeGreaterThan(0);
    });

    it('should estimate bandwidth for Minecraft server', () => {
      const result = estimateBandwidth(100, 'minecraft server');
      expect(result.category).toBeDefined();
      expect(result.monthly_gb).toBeGreaterThan(0);
    });
  });

  describe('File download use cases', () => {
    it('should estimate bandwidth for file download service', () => {
      const result = estimateBandwidth(300, 'file download service');
      expect(result.category).toBeDefined();
      expect(result.monthly_tb).toBeGreaterThan(0);
    });

    it('should estimate higher bandwidth for large files', () => {
      const result = estimateBandwidth(200, 'ISO download service');
      expect(result.monthly_tb).toBeGreaterThan(1);
    });
  });

  describe('Chat and messaging', () => {
    it('should estimate bandwidth for chat application', () => {
      const result = estimateBandwidth(500, 'chat application');
      expect(result.category).toBeDefined();
      expect(result.active_ratio).toBeGreaterThan(0.5);
    });

    it('should estimate bandwidth for messaging platform', () => {
      const result = estimateBandwidth(1000, 'messaging platform like Slack');
      expect(result.category).toBeDefined();
      expect(result.monthly_gb).toBeGreaterThan(0);
    });
  });

  describe('Forum and community', () => {
    it('should estimate bandwidth for forum', () => {
      const result = estimateBandwidth(800, 'community forum');
      expect(result.category).toBeDefined();
      expect(result.monthly_gb).toBeGreaterThan(0);
    });

    it('should estimate bandwidth for Korean forum', () => {
      const result = estimateBandwidth(500, '커뮤니티 게시판');
      expect(result.category).toBeDefined();
      expect(result.monthly_gb).toBeGreaterThan(0);
    });
  });

  describe('Traffic patterns', () => {
    it('should apply multiplier for spiky traffic', () => {
      const steady = estimateBandwidth(500, 'web api', 'steady');
      const spiky = estimateBandwidth(500, 'web api', 'spiky');
      expect(spiky.monthly_gb).toBeGreaterThan(steady.monthly_gb);
    });

    it('should apply multiplier for growing traffic', () => {
      const steady = estimateBandwidth(500, 'web api', 'steady');
      const growing = estimateBandwidth(500, 'web api', 'growing');
      expect(growing.monthly_gb).toBeGreaterThan(steady.monthly_gb);
    });

    it('should not change bandwidth for steady traffic', () => {
      const noPattern = estimateBandwidth(500, 'web api');
      const steady = estimateBandwidth(500, 'web api', 'steady');
      expect(noPattern.monthly_gb).toBe(steady.monthly_gb);
    });
  });

  describe('Bandwidth categorization', () => {
    it('should categorize light bandwidth correctly', () => {
      const result = estimateBandwidth(50, 'blog');
      expect(result.category).toBe('light');
      expect(result.monthly_tb).toBeLessThan(0.5);
    });

    it('should categorize moderate bandwidth correctly', () => {
      const result = estimateBandwidth(200, 'web application');
      if (result.monthly_tb >= 0.5 && result.monthly_tb < 2) {
        expect(result.category).toBe('moderate');
      }
    });

    it('should categorize heavy bandwidth correctly', () => {
      const result = estimateBandwidth(500, 'e-commerce shop');
      if (result.monthly_tb >= 2 && result.monthly_tb < 6) {
        expect(result.category).toBe('heavy');
      }
    });

    it('should categorize very heavy bandwidth correctly', () => {
      const result = estimateBandwidth(1000, 'video streaming 4K');
      if (result.monthly_tb >= 6) {
        expect(result.category).toBe('very_heavy');
      }
    });
  });

  describe('DAU calculation', () => {
    it('should calculate DAU within expected range', () => {
      const result = estimateBandwidth(100, 'web api');
      expect(result.estimated_dau_min).toBeGreaterThan(0);
      expect(result.estimated_dau_max).toBeGreaterThan(result.estimated_dau_min);
      expect(result.active_ratio).toBeGreaterThan(0);
      expect(result.active_ratio).toBeLessThanOrEqual(1);
    });

    it('should have higher DAU multiplier for blog', () => {
      const blog = estimateBandwidth(100, 'blog');
      const api = estimateBandwidth(100, 'api service');
      // Blog has higher DAU multiplier (30-50x) vs API (5-10x)
      expect(blog.estimated_dau_max).toBeGreaterThan(api.estimated_dau_max);
    });
  });

  describe('Edge cases', () => {
    it('should handle very small concurrent users', () => {
      const result = estimateBandwidth(1, 'simple website');
      expect(result.monthly_gb).toBeGreaterThan(0);
      expect(result.category).toBe('light');
    });

    it('should handle very large concurrent users', () => {
      const result = estimateBandwidth(10000, 'large platform');
      expect(result.monthly_gb).toBeGreaterThan(0);
      expect(result.monthly_tb).toBeGreaterThan(1);
    });

    it('should handle default category for unknown use case', () => {
      const result = estimateBandwidth(100, 'unknown application type');
      expect(result.category).toBeDefined();
      expect(result.monthly_gb).toBeGreaterThan(0);
    });
  });
});
