import {
  buildSlippageSnapshot,
  DEFAULT_SLIPPAGE_PERCENT,
  isRateBelowMinAcceptableRate,
  normalizeSlippageConfigFromMetadata,
  resolveSlippagePercent,
} from '../../src/libs/slippage';

describe('libs/slippage', () => {
  describe('normalizeSlippageConfigFromMetadata', () => {
    it('returns null when no slippage metadata is present', () => {
      expect(normalizeSlippageConfigFromMetadata(null)).toBeNull();
      expect(normalizeSlippageConfigFromMetadata(undefined)).toBeNull();
      expect(normalizeSlippageConfigFromMetadata({})).toBeNull();
    });

    it('normalizes percent mode with fallback percent', () => {
      const result = normalizeSlippageConfigFromMetadata({
        slippage: {
          mode: 'percent',
          percent: 'invalid',
        },
      });

      expect(result).not.toBeNull();
      expect(result?.mode).toBe('percent');
      expect(result?.percent).toBe(DEFAULT_SLIPPAGE_PERCENT);
    });

    it('preserves rate mode config fields', () => {
      const result = normalizeSlippageConfigFromMetadata({
        slippage: {
          mode: 'rate',
          percent: '1.25',
          min_acceptable_rate: '0.9',
          base_currency: 'USD',
          updated_at_ms: 123,
        },
      });

      expect(result).toEqual({
        mode: 'rate',
        percent: 1.25,
        min_acceptable_rate: '0.9',
        base_currency: 'USD',
        updated_at_ms: 123,
      });
    });
  });

  describe('resolveSlippagePercent', () => {
    it('prefers quote slippage percent over session metadata', () => {
      const quote = { slippage_percent: 2 };
      const session = { metadata: { slippage: { percent: 0.5 } }, slippage_percent: 1 };

      expect(resolveSlippagePercent(quote, session)).toBe(2);
    });

    it('falls back to session metadata when quote is missing', () => {
      const quote = { metadata: {} };
      const session = { metadata: { slippage: { percent: 1.1 } } };

      expect(resolveSlippagePercent(quote, session)).toBe(1.1);
    });

    it('falls back to default when values are invalid', () => {
      const quote = { slippage_percent: -1 };

      expect(resolveSlippagePercent(quote, undefined)).toBe(DEFAULT_SLIPPAGE_PERCENT);
    });
  });

  describe('buildSlippageSnapshot', () => {
    it('derives max_payable_token and min_acceptable_rate from percent', () => {
      const snapshot = buildSlippageSnapshot({
        quote: {
          quoted_amount: '1000',
          exchange_rate: '100',
          slippage_percent: 25,
        },
        checkoutSession: { metadata: {} },
        nowMs: 456,
      });

      expect(snapshot).toEqual({
        percent: 25,
        max_payable_token: '1250',
        min_acceptable_rate: '80',
        derived_at_ms: 456,
      });
    });
  });

  describe('isRateBelowMinAcceptableRate', () => {
    it('returns true when current rate is below min acceptable rate', () => {
      expect(isRateBelowMinAcceptableRate('0.9', '1')).toBe(true);
    });

    it('returns false when current rate is above or equal to min acceptable rate', () => {
      expect(isRateBelowMinAcceptableRate('1', '1')).toBe(false);
      expect(isRateBelowMinAcceptableRate('1.1', '1')).toBe(false);
    });

    it('returns false for invalid inputs', () => {
      expect(isRateBelowMinAcceptableRate('abc', '1')).toBe(false);
      expect(isRateBelowMinAcceptableRate('1', 'xyz')).toBe(false);
    });
  });
});
