import { processErrors, getLiquidProps, hasPlatformErrors } from './utils';

const makeMessages = (overrides = {}) => ({
  standardErrorHeader: { id: 'standard', defaultMessage: 'Standard' },
  dynamicErrorHeader: { id: 'liquid', defaultMessage: 'Liquid' },
  ...overrides,
});

// Mock platform constants
const ANDROID = 'ANDROID';
const IOS = 'IOS';

describe('processErrors', () => {
  it('returns empty errors if platform is not specified and input has GENERIC key', () => {
    const messages = makeMessages();
    const raw = { ANDROID: ['a1'], IOS: ['i1'], GENERIC: ['g1', 'g2'] };
    const result = processErrors(raw, 'standard', undefined, messages);
    expect(result.errorsToShow).toEqual([]);
    expect(result.platformLabel).toBeUndefined();
  });

  it('returns empty errors for object input with missing keys', () => {
    const messages = makeMessages();
    const raw = { ANDROID: [], IOS: [], GENERIC: [] };
    const result = processErrors(raw, 'standard', 'ANDROID', messages);
    expect(result.errorsToShow).toEqual([]);
    expect(result.platformLabel).toBe('ANDROID');
  });

  it('returns empty errors for null/undefined/empty input', () => {
    const messages = makeMessages();
    expect(processErrors(null, 'standard', undefined, messages).errorsToShow).toEqual([]);
    expect(processErrors(undefined, 'standard', undefined, messages).errorsToShow).toEqual([]);
    expect(processErrors([], 'standard', undefined, messages).errorsToShow).toEqual([]);
  });

  it('returns empty errors for object input with only GENERIC key', () => {
    const messages = makeMessages();
    const raw = { GENERIC: ['g1', 'g2'] };
    const result = processErrors(raw, 'standard', undefined, messages);
    expect(result.errorsToShow).toEqual([]);
    expect(result.platformLabel).toBeUndefined();
  });

  it('handles object input with only ANDROID/IOS keys', () => {
    const messages = makeMessages();
    const raw = { ANDROID: ['a1'], IOS: ['i1'] };
    const result = processErrors(raw, 'standard', 'ANDROID', messages);
    expect(result.errorsToShow).toEqual(['a1']);
    expect(result.platformLabel).toBe('ANDROID');
  });

  it('handles object input with no errors for currentTab', () => {
    const messages = makeMessages();
    const raw = { ANDROID: [], IOS: ['i1'] };
    const result = processErrors(raw, 'standard', 'ANDROID', messages);
    expect(result.errorsToShow).toEqual([]);
    expect(result.platformLabel).toBe('ANDROID');
  });

  it('returns undefined platformLabel for object input with no GENERIC key and no platform', () => {
    const messages = makeMessages();
    const raw = { ANDROID: ['a1'], IOS: ['i1'] };
    const result = processErrors(raw, 'standard', undefined, messages);
    expect(result.errorsToShow).toEqual([]);
    expect(result.platformLabel).toBeUndefined();
  });

  it('returns correct title and errors for array input with errorType liquid', () => {
    const messages = makeMessages();
    const result = processErrors(['liquidErr1', 'liquidErr2'], 'liquid', undefined, messages);
    expect(result.errorsToShow).toEqual(['liquidErr1', 'liquidErr2']);
    expect(result.title.props.id).toBe('liquid');
    expect(result.title.props.defaultMessage).toBe('Liquid');
    expect(result.platformLabel).toBeNull();
  });

  it('returns correct title and errors for object input with errorType liquid and platform', () => {
    const messages = makeMessages();
    const raw = { ANDROID: ['l1', 'l2'], IOS: ['l3'], GENERIC: ['lg1'] };
    const result = processErrors(raw, 'liquid', 'ANDROID', messages);
    expect(result.errorsToShow).toEqual(['l1', 'l2']);
    expect(result.title.props.id).toBe('liquid');
    expect(result.title.props.defaultMessage).toBe('Liquid');
    expect(result.platformLabel).toBe('ANDROID');
  });

  it('returns empty errors for object input with errorType liquid and no platform', () => {
    const messages = makeMessages();
    const raw = { ANDROID: ['l1'], IOS: ['l2'], GENERIC: ['lg1', 'lg2'] };
    const result = processErrors(raw, 'liquid', undefined, messages);
    expect(result.errorsToShow).toEqual([]);
    expect(result.title.props.id).toBe('liquid');
    expect(result.title.props.defaultMessage).toBe('Liquid');
    expect(result.platformLabel).toBeUndefined();
  });
});

describe('getLiquidProps', () => {
  const baseErrors = {
    STANDARD: { errorsToShow: ['s1'] },
    LIQUID: { errorsToShow: ['l1'], title: 'Liquid Title' },
  };

  it('returns correct props for Android with showTitle true and showPlatformLabels true', () => {
    const result = getLiquidProps(baseErrors, true, true, true);
    expect(result).toEqual({
      title: 'Liquid Title',
      errors: ['s1', 'l1'],
      liquidError: true,
      platformLabel: ANDROID,
    });
  });

  it('returns correct props for iOS with showTitle false and showPlatformLabels true', () => {
    const result = getLiquidProps(baseErrors, false, false, true);
    expect(result).toEqual({
      title: 'Liquid Title',
      errors: ['s1', 'l1'],
      liquidError: true,
      platformLabel: IOS,
    });
  });

  it('returns title even when showTitle is false for Android', () => {
    const result = getLiquidProps(baseErrors, true, false, true);
    expect(result.title).toBe('Liquid Title');
  });

  it('returns title even when showTitle is false for iOS', () => {
    const result = getLiquidProps(baseErrors, false, false, true);
    expect(result.title).toBe('Liquid Title');
  });

  it('returns platformLabel null if showPlatformLabels is false', () => {
    const result = getLiquidProps(baseErrors, true, true, false);
    expect(result.platformLabel).toBeNull();
  });

  it('returns empty errors array if both errorsToShow are missing', () => {
    const result = getLiquidProps({}, true, true, true);
    expect(result.errors).toEqual([]);
  });

  it('liquidError is false if no liquid errors', () => {
    const result = getLiquidProps({ STANDARD: { errorsToShow: ['s1'] } }, true, true, true);
    expect(result.liquidError).toBe(false);
  });

  it('handles undefined input gracefully', () => {
    const result = getLiquidProps(undefined, true, true, true);
    expect(result.errors).toEqual([]);
    expect(result.liquidError).toBe(false);
    expect(result.platformLabel).toBe(ANDROID);
  });
});

describe('hasPlatformErrors', () => {
  it('returns false for null, undefined, or empty object', () => {
    expect(hasPlatformErrors(null)).toBe(false);
    expect(hasPlatformErrors(undefined)).toBe(false);
    expect(hasPlatformErrors({})).toBe(false);
  });

  it('returns false if both STANDARD.errorsToShow and LIQUID.errorsToShow are missing or empty', () => {
    expect(hasPlatformErrors({ STANDARD: { errorsToShow: [] }, LIQUID: { errorsToShow: [] } })).toBe(false);
    expect(hasPlatformErrors({ STANDARD: {}, LIQUID: {} })).toBe(false);
    expect(hasPlatformErrors({})).toBe(false);
  });

  it('returns true if STANDARD.errorsToShow has items', () => {
    expect(hasPlatformErrors({ STANDARD: { errorsToShow: [1, 2] }, LIQUID: { errorsToShow: [] } })).toBe(true);
  });

  it('returns true if LIQUID.errorsToShow has items', () => {
    expect(hasPlatformErrors({ STANDARD: { errorsToShow: [] }, LIQUID: { errorsToShow: [1] } })).toBe(true);
  });

  it('returns true if both STANDARD and LIQUID errorsToShow have items', () => {
    expect(hasPlatformErrors({ STANDARD: { errorsToShow: [1] }, LIQUID: { errorsToShow: [2] } })).toBe(true);
  });

  it('handles missing STANDARD or LIQUID keys gracefully', () => {
    expect(hasPlatformErrors({ STANDARD: { errorsToShow: [1] } })).toBe(true);
    expect(hasPlatformErrors({ LIQUID: { errorsToShow: [2] } })).toBe(true);
    expect(hasPlatformErrors({ STANDARD: {}, LIQUID: undefined })).toBe(false);
    expect(hasPlatformErrors({ STANDARD: undefined, LIQUID: {} })).toBe(false);
  });
});
