/**
 * Генератор временных ID для offline заметок
 */
export function generateTempId(): string {
  return `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}

/**
 * Проверка, является ли ID временным
 */
export function isTempId(id: number | string): boolean {
  return typeof id === 'string' && id.startsWith('temp-');
}

/**
 * Ожидание доступности IndexedDB
 */
export function waitForIndexedDB(): Promise<IDBDatabase> {
  return new Promise((resolve, reject) => {
    const request = indexedDB.open('test-db', 1);
    
    request.onerror = () => {
      reject(request.error);
    };
    
    request.onsuccess = () => {
      const db = request.result;
      db.close();
      indexedDB.deleteDatabase('test-db');
      resolve(request.result);
    };
    
    request.onupgradeneeded = (event) => {
      const db = (event.target as IDBOpenDBRequest).result;
      db.createObjectStore('test');
    };
  });
}

/**
 * Проверка состояния сети (более надежный метод)
 */
export async function checkNetworkStatus(): Promise<boolean> {
  // Простая проверка navigator.onLine
  if (!navigator.onLine) {
    return false;
  }

  // Дополнительная проверка через fetch с коротким таймаутом
  // Используем короткий таймаут для быстрого определения оффлайна
  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 2000);
    
    // Используем /auth/status так как он всегда доступен при наличии сети
    const response = await fetch('/api/auth/status', {
      method: 'GET',
      signal: controller.signal,
      cache: 'no-cache',
      credentials: 'include', // Важно для cookie-based auth
    });
    
    clearTimeout(timeoutId);
    return response.ok;
  } catch (error: any) {
    // Если запрос не удался, проверяем тип ошибки
    const isAbortError = error.name === 'AbortError'; // Таймаут
    const isNetworkError = 
      error.message === 'Failed to fetch' ||
      error.message?.includes('NetworkError') ||
      error.message?.includes('ERR_INTERNET_DISCONNECTED') ||
      error.message?.includes('ERR_NETWORK') ||
      error.message?.includes('network request failed');
    
    // Если это явная сетевая ошибка (не таймаут), точно оффлайн
    if (isNetworkError && !isAbortError) {
      return false;
    }
    
    // Если это таймаут, проверяем navigator.onLine
    // Таймаут может быть как из-за оффлайна, так и из-за медленного соединения
    if (isAbortError) {
      // Если navigator.onLine = false, точно оффлайн
      if (!navigator.onLine) {
        return false;
      }
      // Если navigator.onLine = true, но таймаут - возможно медленное соединение
      // Но для безопасности считаем оффлайном, так как запрос не прошел
      return false;
    }
    
    // Если это не сетевая ошибка и не таймаут (например, CORS или другая проблема),
    // но navigator.onLine = true, считаем что онлайн
    // (возможно, просто другая проблема, но сеть есть)
    return navigator.onLine;
  }
}

/**
 * Проверка, доступна ли БД на клиенте
 */
export function isDatabaseAvailable(): boolean {
  return typeof indexedDB !== 'undefined';
}

/**
 * Сохранение blob в base64
 */
export function fileToBase64(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      if (typeof reader.result === 'string') {
        resolve(reader.result);
      } else {
        reject(new Error('Failed to convert file to base64'));
      }
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

/**
 * Конвертация base64 обратно в Blob
 */
export function base64ToBlob(base64: string, mimeType: string): Blob {
  const byteCharacters = atob(base64.split(',')[1] || base64);
  const byteNumbers = new Array(byteCharacters.length);
  for (let i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
  }
  const byteArray = new Uint8Array(byteNumbers);
  return new Blob([byteArray], { type: mimeType });
}

/**
 * Получение размера base64 строки в байтах
 */
export function getBase64Size(base64: string): number {
  const base64String = base64.split(',')[1] || base64;
  return Math.ceil((base64String.length * 3) / 4);
}

/**
 * Создание Listener для событий сети
 */
export class NetworkListener {
  private onlineHandler: ((event: Event) => void) | null = null;
  private offlineHandler: ((event: Event) => void) | null = null;

  onOnline(callback: (event: Event) => void): void {
    this.onlineHandler = callback;
    window.addEventListener('online', callback);
  }

  onOffline(callback: (event: Event) => void): void {
    this.offlineHandler = callback;
    window.addEventListener('offline', callback);
  }

  removeListeners(): void {
    if (this.onlineHandler) {
      window.removeEventListener('online', this.onlineHandler);
      this.onlineHandler = null;
    }
    if (this.offlineHandler) {
      window.removeEventListener('offline', this.offlineHandler);
      this.offlineHandler = null;
    }
  }
}

export const networkListener = new NetworkListener();

