import {
  describe,
  expect,
  it
} from 'vitest';

import translationsEn from '../../../../../public/i18n/en.json';
import {
  buildMobileUpdateState,
  createInitialMobileUpdateState,
  getMobileUpdateStatusLabel,
  mapUpdateAvailabilityToStatus,
  resolveMobileUpdateStatusMessage
} from './mobile-app-update.rules';
import type { MobileAppUpdateInfoSnapshot } from './mobile-app-update.rules';

function instant(key: string, params?: Record<string, string | number>): string {
  const value = key.split('.').reduce<unknown>((current, part) => {
    if (current && typeof current === 'object') {
      return (current as Record<string, unknown>)[part];
    }

    return undefined;
  }, translationsEn);

  if (typeof value !== 'string') {
    return key;
  }

  return Object.entries(params ?? {}).reduce(
    (message, [paramKey, paramValue]) => message.replace(`{{${paramKey}}}`, String(paramValue)),
    value
  );
}

describe('mobile-app-update.rules', () => {
  it('creates an idle unsupported state for non-native shells', () => {
    const state = createInitialMobileUpdateState({ isSupported: false, translate: instant });

    expect(state.status).toBe('unsupported');
    expect(state.isSupported).toBe(false);
    expect(state.currentVersion).toBe('0.0.0');
  });

  it('maps update availability to mobile update statuses', () => {
    expect(mapUpdateAvailabilityToStatus('checking')).toBe('checking');
    expect(mapUpdateAvailabilityToStatus('update-available')).toBe('update-available');
    expect(mapUpdateAvailabilityToStatus('update-not-available')).toBe('up-to-date');
    expect(mapUpdateAvailabilityToStatus('unknown')).toBe('idle');
  });

  it('builds an update-available state from store metadata', () => {
    const snapshot: MobileAppUpdateInfoSnapshot = {
      availableVersion: '1.2.0',
      currentVersion: '1.1.0',
      flexibleUpdateAllowed: true,
      immediateUpdateAllowed: false,
      platform: 'android',
      updateAvailability: 'update-available'
    };
    const state = buildMobileUpdateState(snapshot, {
      isSupported: true,
      lastCheckedAt: 1_700_000_000_000,
      translate: instant
    });

    expect(state.status).toBe('update-available');
    expect(state.availableVersion).toBe('1.2.0');
    expect(state.currentVersion).toBe('1.1.0');
    expect(state.flexibleUpdateAllowed).toBe(true);
    expect(state.immediateUpdateAllowed).toBe(false);
    expect(state.lastCheckedAt).toBe(1_700_000_000_000);
    expect(state.statusMessage).toContain('1.2.0');
  });

  it('builds an up-to-date state when the store reports no update', () => {
    const snapshot: MobileAppUpdateInfoSnapshot = {
      availableVersion: null,
      currentVersion: '1.1.0',
      flexibleUpdateAllowed: false,
      immediateUpdateAllowed: false,
      platform: 'ios',
      updateAvailability: 'update-not-available'
    };
    const state = buildMobileUpdateState(snapshot, { isSupported: true, translate: instant });

    expect(state.status).toBe('up-to-date');
    expect(state.statusMessage).toContain('up to date');
  });

  it('maps errors to a friendly status message', () => {
    expect(resolveMobileUpdateStatusMessage('error', new Error('Required app information could not be fetched'), null, instant))
      .toContain('store');

    expect(getMobileUpdateStatusLabel('update-available', instant)).toBe('Update available');
  });
});
