import { GenerationResponse, ApiError as ApiErrorType, GeneratedImage, PendingTask, GenerationResult } from '../types/api';
import { baseWorkflow } from '../constants/baseWorkflow';
import { prompts } from '../assets/prompts';
import translateService from './translateService';
import { getCurrentUserId, isTelegramWebAppAvailable } from '../constants/user';
import { trackStickerGeneration, trackRejectedPrompt } from './analyticsService';

const API_BASE_URL = 'https://stickerserver.gymnasticstuff.uk';

/**
 * Нормализует URL изображения, заменяя IP-адрес на домен, если необходимо.
 * Если URL уже содержит домен, оставляет его без изменений.
 * @param url URL изображения
 * @returns Нормализованный URL
 */
export const normalizeImageUrl = (url: string): string => {
  if (!url) return url;
  
  // Если URL уже содержит домен, оставляем его без изменений
  if (url.includes('stickerserver.gymnasticstuff.uk')) {
    return url;
  }
  
  // Проверяем, содержит ли URL IP-адрес (простая проверка на наличие цифр и точек)
  const ipRegex = /\d+\.\d+\.\d+\.\d+/;
  if (ipRegex.test(url)) {
    // Заменяем IP-адрес на домен
    // Извлекаем путь из URL (все, что после IP-адреса и порта, если есть)
    const pathMatch = url.match(/https?:\/\/\d+\.\d+\.\d+\.\d+(:\d+)?(\/.*)/);
    if (pathMatch && pathMatch[2]) {
      return `${API_BASE_URL}${pathMatch[2]}`;
    }
  }
  
  return url;
};

// Маппинг стилей к тегам для определения, какой тег использовать для каждого стиля
const styleToTagMap: Record<string, string> = {
  'chibi': 'image_generation',
  'emotions': 'chibi', // Пока используем chibi для всех стилей
  'realism': 'chibi'
};

class GenerationError extends Error {
  constructor(public details: ApiErrorType['detail']) {
    super('API Error');
    this.name = 'GenerationError';
  }
}

// Временное решение для работы с балансом токенов
// Используется только если не удалось получить баланс с сервера
let mockBalance = 50; // Начальное значение из MOCK_USER

const apiService = {
  // Метод для получения информации о пользователе
  async getUserInfo(userId: number = getCurrentUserId()): Promise<any> {
    try {
      const response = await fetch(`${API_BASE_URL}/users/${userId}`, {
        method: 'GET',
        headers: {
          'accept': 'application/json',
        }
      });

      if (!response.ok) {
        throw new Error('Failed to fetch user info');
      }

      return await response.json();
    } catch (error) {
      console.error('Error fetching user info:', error);
      throw error;
    }
  },

  // Метод для создания ссылки на инвойс
  async createInvoiceLink(userId: number, starsAmount: number, tokens: number): Promise<string> {
    try {
      const response = await fetch(`${API_BASE_URL}/create-invoice-link?user_id=${userId}&stars_amount=${starsAmount}&tokens=${tokens}`, {
        method: 'POST',
        headers: {
          'accept': 'application/json',
        }
      });

      if (!response.ok) {
        throw new Error('Failed to create invoice link');
      }

      // Парсим ответ как JSON и извлекаем поле invoice_link
      const data = await response.json();
      if (!data.invoice_link) {
        throw new Error('Invalid response format: missing invoice_link field');
      }
      
      return data.invoice_link;
    } catch (error) {
      console.error('Error creating invoice link:', error);
      throw error;
    }
  },

  // Метод для получения текущего баланса
  async getBalance(userId: number = getCurrentUserId()): Promise<number> {
    try {
      const userInfo = await this.getUserInfo(userId);
      return userInfo.balance || 0;
    } catch (error) {
      console.error('Error getting balance:', error);
      // В случае ошибки возвращаем mockBalance для обратной совместимости
      return mockBalance;
    }
  },

  // Получение списка задач пользователя в статусе PENDING
  async getUserPendingTasks(userId = getCurrentUserId()): Promise<PendingTask[]> {
    try {
      const response = await fetch(`${API_BASE_URL}/user_pending_tasks/${userId}`, {
        method: 'GET',
        headers: {
          'accept': 'application/json',
        }
      });

      if (!response.ok) {
        throw new Error('Failed to fetch pending tasks');
      }

      return await response.json();
    } catch (error) {
      console.error('Error fetching pending tasks:', error);
      return [];
    }
  },

  // Получение текущей позиции задачи в очереди
  async getTaskPosition(taskId: string): Promise<{task_id: number, status: string, queue_position: number | null}> {
    try {
      const response = await fetch(`${API_BASE_URL}/task_position/${taskId}`, {
        method: 'GET',
        headers: {
          'accept': 'application/json',
        }
      });

      if (!response.ok) {
        throw new Error('Failed to fetch task position');
      }

      return await response.json();
    } catch (error) {
      console.error('Error fetching task position:', error);
      throw error;
    }
  },

  // Расчет примерного времени ожидания в секундах
  calculateEstimatedWaitTime(queuePosition: number): number {
    // Среднее время генерации 13-15 секунд
    const averageGenerationTime = 14; 
    return queuePosition * averageGenerationTime;
  },

  async getGeneratedImages(userId = getCurrentUserId()): Promise<GeneratedImage[]> {
    try {
      const response = await fetch(`${API_BASE_URL}/images_links/${userId}`, {
        method: 'GET',
        headers: {
          'accept': 'application/json',
        }
      });

      if (!response.ok) {
        throw new Error('Failed to fetch images');
      }

      // Получаем массив массивов [file_id, created_at]
      const rawData = await response.json() as [string, string][];
      
      // Преобразуем в массив объектов GeneratedImage
      const images = rawData.map((item, index) => {
        const [fileId, createdAt] = item;
        return {
          id: index + 1,
          link: fileId,
          prompt_id: '',
          status: 'COMPLETED',
          created_at: createdAt,
          sticker_set_id: null,
          url: `${API_BASE_URL}/stickers/proxy/sticker/${encodeURIComponent(fileId)}`
        };
      });
      
      // Сортируем изображения от новых к старым по дате создания
      return images.sort((a, b) => 
        new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
      );
    } catch (error) {
      console.error('Error fetching images:', error);
      throw new Error('Failed to fetch images');
    }
  },
  
  // Удаление изображения по file_id
  async deleteImage(fileId: string): Promise<string> {
    try {
      const response = await fetch(`${API_BASE_URL}/delete-by-link?link=${encodeURIComponent(fileId)}`, {
        method: 'DELETE',
        headers: {
          'accept': 'application/json',
        }
      });

      if (!response.ok) {
        throw new Error('Failed to delete image');
      }

      return await response.json();
    } catch (error) {
      console.error('Error deleting image:', error);
      throw new Error('Failed to delete image');
    }
  },
  
  async generateImage(imageData: string, style?: string, promptId?: string, userPrompt?: string): Promise<GenerationResult> {
    try {
      // Создаем копию базового воркфлоу
      const workflow = JSON.parse(JSON.stringify(baseWorkflow));
      
      // Вставляем изображение в base64 формате в узел 563
      workflow['563'].inputs.image = imageData;
      
      // Переменная для хранения использованного промпта
      let usedPrompt = '';
      let translationFailed = false;
      
      // Если указан пользовательский промпт и выбрана кнопка "Свой промпт"
      if (userPrompt && promptId === 'customPrompt') {
        console.log('Переводим пользовательский промпт:', userPrompt);
        
        // Используем новый метод перевода через LLM
        const translationResult = await translateService.translateWithLLM(userPrompt);
        
        if (translationResult.success) {
          // Успешный перевод
          console.log('Переведенный промпт:', translationResult.text);
          workflow['316'].inputs.prompt_1 = translationResult.text;
          usedPrompt = translationResult.text;
        } else {
          // Перевод не удался после всех попыток
          console.error('Не удалось перевести промпт:', translationResult.text);
          translationFailed = true;
          
          // Отслеживаем событие неудавшейся генерации
          trackRejectedPrompt(userPrompt);
          
          // Не продолжаем генерацию, возвращаем ошибку с сообщением
          return {
            translationFailed: true,
            usedPrompt: 'Недопустимый промпт', // Сообщение для пользователя
            errorDetails: translationResult.text // Детали ошибки для отладки
          };
        }
      } 
      // Иначе используем предустановленный промпт (они уже переведены)
      else if (promptId && prompts[promptId]) {
        workflow['316'].inputs.prompt_1 = prompts[promptId];
        usedPrompt = prompts[promptId];
        console.log('Используем предустановленный промпт:', prompts[promptId]);
      }
      
      // Если был сбой перевода, не продолжаем генерацию
      if (translationFailed) {
        return { translationFailed: true };
      }
      
      // Создаем строку JSON для workflow ПОСЛЕ того, как все изменения внесены
      const workflowJson = JSON.stringify(workflow);
      
      // Определяем тег на основе выбранного стиля
      const tag = styleToTagMap[style || 'chibi'] || 'chibi';
      console.log(`Используем тег "${tag}" для стиля "${style || 'chibi'}"`);
      
      // Создаем тело запроса как строку JSON вручную
      const requestBodyJson = `{"tag":"${tag}","user_id":${getCurrentUserId()},"workflow":${workflowJson}}`;
      
      // Сохраняем JSON для отладки только при локальной разработке
      if (!isTelegramWebAppAvailable()) {
        const blob = new Blob([requestBodyJson], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'generation_request.json';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
      }
      
      // Отправляем запрос
      const response = await fetch(`${API_BASE_URL}/generate_image`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: requestBodyJson
      });

      if (!response.ok) {
        const errorData: ApiErrorType = await response.json();
        throw new GenerationError(errorData.detail);
      }

      const result = await response.json() as GenerationResponse;
      
      // Отслеживаем событие генерации стикера
      trackStickerGeneration(usedPrompt);
      
      // Возвращаем результат и использованный промпт
      return {
        result,
        usedPrompt,
        translationFailed: false
      };
    } catch (error) {
      if (error instanceof GenerationError) {
        throw error;
      }
      throw new Error('Failed to generate image');
    }
  }
};

export default apiService;
