import {
  parsePurchaseDates,
  coerceSkuType,
  mapToNamiPaywallAction,
  parseEntitlements,
} from '../transformers';
import { NamiPaywallAction } from '../types';

describe('parsePurchaseDates', () => {
  it('converts timestamp numbers to Date objects', () => {
    const raw = {
      skuId: 'com.example.monthly',
      purchaseInitiatedTimestamp: 1700000000000,
      expires: 1700086400000,
    };
    const result = parsePurchaseDates(raw);

    expect(result.purchaseInitiatedTimestamp).toBeInstanceOf(Date);
    expect(result.purchaseInitiatedTimestamp.getTime()).toBe(1700000000000);
    expect(result.expires).toBeInstanceOf(Date);
    expect(result.expires!.getTime()).toBe(1700086400000);
  });

  it('sets expires to undefined when absent', () => {
    const raw = {
      skuId: 'com.example.lifetime',
      purchaseInitiatedTimestamp: 1700000000000,
    };
    const result = parsePurchaseDates(raw);

    expect(result.expires).toBeUndefined();
  });

  it('sets expires to undefined when explicitly null', () => {
    const raw = {
      skuId: 'com.example.lifetime',
      purchaseInitiatedTimestamp: 1700000000000,
      expires: null,
    };
    const result = parsePurchaseDates(raw);

    expect(result.expires).toBeUndefined();
  });

  it('preserves all other fields via spread', () => {
    const raw = {
      skuId: 'com.example.monthly',
      transactionIdentifier: 'txn_123',
      purchaseSource: 'CAMPAIGN' as const,
      purchaseInitiatedTimestamp: 1700000000000,
      sku: { id: 'sku_1', skuId: 'com.example.monthly', type: 'subscription' },
    };
    const result = parsePurchaseDates(raw);

    expect(result.skuId).toBe('com.example.monthly');
    expect(result.transactionIdentifier).toBe('txn_123');
    expect(result.purchaseSource).toBe('CAMPAIGN');
    expect(result.sku).toEqual(raw.sku);
  });
});

describe('coerceSkuType', () => {
  it.each(['unknown', 'one_time_purchase', 'subscription'] as const)(
    'accepts valid type "%s"',
    (type) => {
      expect(coerceSkuType(type)).toBe(type);
    },
  );

  it('returns "unknown" for invalid types', () => {
    expect(coerceSkuType('invalid')).toBe('unknown');
    expect(coerceSkuType('')).toBe('unknown');
    expect(coerceSkuType('SUBSCRIPTION')).toBe('unknown');
  });
});

describe('mapToNamiPaywallAction', () => {
  it.each(Object.values(NamiPaywallAction))(
    'accepts valid action "%s"',
    (action) => {
      expect(mapToNamiPaywallAction(action)).toBe(action);
    },
  );

  it('returns UNKNOWN for unrecognized actions', () => {
    expect(mapToNamiPaywallAction('NOT_A_REAL_ACTION')).toBe(
      NamiPaywallAction.UNKNOWN,
    );
    expect(mapToNamiPaywallAction('')).toBe(NamiPaywallAction.UNKNOWN);
    expect(mapToNamiPaywallAction('buy_sku')).toBe(NamiPaywallAction.UNKNOWN);
  });
});

describe('parseEntitlements', () => {
  const rawPurchase = {
    skuId: 'com.example.monthly',
    purchaseInitiatedTimestamp: 1700000000000,
    expires: 1700086400000,
  };

  it('converts activePurchases dates', () => {
    const raw = [
      {
        name: 'Premium',
        desc: 'Premium access',
        referenceId: 'premium',
        activePurchases: [rawPurchase],
        purchasedSkus: [{ id: 'sku_1', skuId: 'com.example.monthly', type: 'subscription' }],
        relatedSkus: [],
      },
    ];
    const result = parseEntitlements(raw);

    expect(result).toHaveLength(1);
    expect(result[0].activePurchases[0].purchaseInitiatedTimestamp).toBeInstanceOf(Date);
    expect(result[0].activePurchases[0].expires).toBeInstanceOf(Date);
  });

  it('defaults relatedSkus and purchasedSkus to empty arrays when missing', () => {
    const raw = [
      {
        name: 'Basic',
        desc: 'Basic access',
        referenceId: 'basic',
        activePurchases: [],
      },
    ];
    const result = parseEntitlements(raw);

    expect(result[0].relatedSkus).toEqual([]);
    expect(result[0].purchasedSkus).toEqual([]);
  });

  it('preserves existing relatedSkus and purchasedSkus', () => {
    const sku = { id: 'sku_1', skuId: 'com.example.monthly', type: 'subscription' };
    const raw = [
      {
        name: 'Premium',
        desc: 'Premium access',
        referenceId: 'premium',
        activePurchases: [],
        purchasedSkus: [sku],
        relatedSkus: [sku],
      },
    ];
    const result = parseEntitlements(raw);

    expect(result[0].purchasedSkus).toEqual([sku]);
    expect(result[0].relatedSkus).toEqual([sku]);
  });

  it('handles empty array', () => {
    expect(parseEntitlements([])).toEqual([]);
  });

  it('handles multiple entitlements', () => {
    const raw = [
      {
        name: 'A',
        desc: '',
        referenceId: 'a',
        activePurchases: [rawPurchase],
      },
      {
        name: 'B',
        desc: '',
        referenceId: 'b',
        activePurchases: [rawPurchase, rawPurchase],
      },
    ];
    const result = parseEntitlements(raw);

    expect(result).toHaveLength(2);
    expect(result[0].activePurchases).toHaveLength(1);
    expect(result[1].activePurchases).toHaveLength(2);
  });
});
