export type AppTranslateFn = (key: string, params?: Record<string, string | number>) => string;

export type MobileUpdateAvailability = 'unknown' | 'update-available' | 'update-not-available' | 'checking';

export type MobileUpdateStatus =
  | 'idle'
  | 'checking'
  | 'downloading'
  | 'up-to-date'
  | 'update-available'
  | 'unsupported'
  | 'error';

export type MobileUpdatePlatform = 'android' | 'ios' | null;

export interface MobileAppUpdateInfoSnapshot {
  availableVersion: string | null;
  currentVersion: string;
  flexibleUpdateAllowed: boolean;
  immediateUpdateAllowed: boolean;
  platform: MobileUpdatePlatform;
  updateAvailability: MobileUpdateAvailability;
}

export interface MobileUpdateState {
  availableVersion: string | null;
  currentVersion: string;
  flexibleUpdateAllowed: boolean;
  immediateUpdateAllowed: boolean;
  isSupported: boolean;
  lastCheckedAt: number | null;
  platform: MobileUpdatePlatform;
  status: MobileUpdateStatus;
  statusMessage: string | null;
}

export function createInitialMobileUpdateState(
  options: { isSupported: boolean; currentVersion?: string; translate?: AppTranslateFn } = { isSupported: false }
): MobileUpdateState {
  const translate = options.translate ?? identityTranslate;

  return {
    availableVersion: null,
    currentVersion: options.currentVersion ?? '0.0.0',
    flexibleUpdateAllowed: false,
    immediateUpdateAllowed: false,
    isSupported: options.isSupported,
    lastCheckedAt: null,
    platform: null,
    status: options.isSupported ? 'idle' : 'unsupported',
    statusMessage: options.isSupported
      ? translate('mobile.update.messages.waitingForCheck')
      : translate('mobile.update.messages.unsupported')
  };
}

export function mapUpdateAvailabilityToStatus(
  availability: MobileUpdateAvailability
): MobileUpdateStatus {
  switch (availability) {
    case 'checking':
      return 'checking';
    case 'update-available':
      return 'update-available';
    case 'update-not-available':
      return 'up-to-date';
    default:
      return 'idle';
  }
}

export function buildMobileUpdateState(
  snapshot: MobileAppUpdateInfoSnapshot,
  options: {
    isSupported: boolean;
    lastCheckedAt?: number | null;
    statusOverride?: MobileUpdateStatus;
    statusMessage?: string | null;
    translate?: AppTranslateFn;
  }
): MobileUpdateState {
  const translate = options.translate ?? identityTranslate;
  const status = options.statusOverride ?? mapUpdateAvailabilityToStatus(snapshot.updateAvailability);

  return {
    availableVersion: snapshot.availableVersion,
    currentVersion: snapshot.currentVersion,
    flexibleUpdateAllowed: snapshot.flexibleUpdateAllowed,
    immediateUpdateAllowed: snapshot.immediateUpdateAllowed,
    isSupported: options.isSupported,
    lastCheckedAt: options.lastCheckedAt ?? null,
    platform: snapshot.platform,
    status,
    statusMessage: options.statusMessage ?? resolveMobileUpdateStatusMessage(status, null, snapshot, translate)
  };
}

export function resolveMobileUpdateStatusMessage(
  status: MobileUpdateStatus,
  error: unknown = null,
  snapshot: MobileAppUpdateInfoSnapshot | null = null,
  translate: AppTranslateFn = identityTranslate
): string | null {
  if (status === 'error') {
    const message = error instanceof Error ? error.message : String(error ?? '');

    if (message.includes('Required app information could not be fetched')) {
      return translate('mobile.update.messages.storeInfoFailed');
    }

    return message.trim() || translate('mobile.update.messages.checkFailed');
  }

  if (status === 'unsupported') {
    return translate('mobile.update.messages.unsupported');
  }

  if (status === 'checking') {
    return translate('mobile.update.messages.checking');
  }

  if (status === 'downloading') {
    return translate('mobile.update.messages.downloading');
  }

  if (status === 'update-available' && snapshot?.availableVersion) {
    return translate('mobile.update.messages.updateAvailable', { version: snapshot.availableVersion });
  }

  if (status === 'up-to-date' && snapshot?.currentVersion) {
    return translate('mobile.update.messages.upToDate', { version: snapshot.currentVersion });
  }

  if (status === 'idle') {
    return translate('mobile.update.messages.waitingForCheck');
  }

  return null;
}

export function getMobileUpdateStatusLabel(
  status: MobileUpdateStatus,
  translate: AppTranslateFn = identityTranslate
): string {
  switch (status) {
    case 'checking':
      return translate('mobile.update.statusLabels.checking');
    case 'downloading':
      return translate('mobile.update.statusLabels.downloading');
    case 'update-available':
      return translate('mobile.update.statusLabels.updateAvailable');
    case 'up-to-date':
      return translate('mobile.update.statusLabels.upToDate');
    case 'unsupported':
      return translate('mobile.update.statusLabels.unsupported');
    case 'error':
      return translate('mobile.update.statusLabels.error');
    default:
      return translate('mobile.update.statusLabels.idle');
  }
}

function identityTranslate(key: string, params?: Record<string, string | number>): string {
  let value = key;

  if (params) {
    for (const [paramKey, paramValue] of Object.entries(params)) {
      value = value.replace(`{{${paramKey}}}`, String(paramValue));
    }
  }

  return value;
}
