import { API_CONFIG, DEFAULT_REQUEST_CONFIG } from '@/config/api.js';

class ReportService {
    constructor() {
        this.baseURL = API_CONFIG.BASE_URL;
        this.endpoints = {
            GENERATE: API_CONFIG.ENDPOINTS.REPORT_GENERATE,
            HISTORY: API_CONFIG.ENDPOINTS.REPORT_HISTORY,
            DOWNLOAD: API_CONFIG.ENDPOINTS.REPORT_DOWNLOAD
        };
    }

    /**
     * Генерирует новый отчёт
     * @param {Object} reportData - Данные для генерации отчёта
     * @param {string} reportData.query - Тема для исследования
     * @param {string} reportData.lang - Язык отчёта ("ru", "en")
     * @param {number} reportData.depth - Глубина исследования (1-5)
     * @param {number} reportData.breadth - Широта исследования (2-10)
     * @param {string} reportData.report_type - Тип отчёта ("report", "answer")
     * @returns {Promise<Blob>} - PDF-файл с отчётом
     */
    async generateReport(reportData) {
        try {
            const response = await fetch(`${this.baseURL}${this.endpoints.GENERATE}`, {
                method: 'POST',
                headers: {
                    ...DEFAULT_REQUEST_CONFIG.headers,
                    Authorization: `Bearer ${this.getAuthToken()}`
                },
                body: JSON.stringify(reportData)
            });

            if (!response.ok) {
                const errorText = await response.text();
                throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
            }

            const contentType = response.headers.get('Content-Type') || '';

            // Если пришёл PDF/бинарный файл — вернуть как blob
            if (contentType.includes('application/pdf') || contentType.includes('application/octet-stream')) {
                const blob = await response.blob();
                const filename = this.getFilenameFromResponse(response) || 'report.pdf';
                return { type: 'blob', blob, filename };
            }

            // В противном случае — попробовать прочитать текст/JSON сообщение
            const text = await response.text();
            try {
                const json = JSON.parse(text);
                const message = json.message || text || 'Операция выполнена';
                return { type: 'message', message };
            } catch (_) {
                return { type: 'message', message: text || 'Операция выполнена' };
            }
        } catch (error) {
            console.error('Ошибка при генерации отчёта:', error);
            throw error;
        }
    }

    /**
     * Получает историю отчётов с пагинацией
     * @param {number} page - Номер страницы (начиная с 0)
     * @param {number} size - Количество элементов на странице
     * @param {string} sort - Поле и направление сортировки
     * @returns {Promise<Object>} - Объект с данными пагинации и списком отчётов
     */
    async getReportHistory(page = 0, size = 20, sort = 'createdAt,desc') {
        try {
            const params = new URLSearchParams({
                page: page.toString(),
                size: size.toString(),
                sort: sort
            });

            const response = await fetch(`${this.baseURL}${this.endpoints.HISTORY}?${params}`, {
                method: 'GET',
                headers: {
                    ...DEFAULT_REQUEST_CONFIG.headers,
                    Authorization: `Bearer ${this.getAuthToken()}`
                }
            });

            if (!response.ok) {
                const errorText = await response.text();
                throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
            }

            return await response.json();
        } catch (error) {
            console.error('Ошибка при получении истории отчётов:', error);
            throw error;
        }
    }

    /**
     * Генерирует и скачивает отчёт
     * @param {Object} reportData - Данные для генерации отчёта
     * @param {string} reportData.query - Тема для исследования
     * @param {string} reportData.lang - Язык отчёта ("ru", "en")
     * @param {number} reportData.depth - Глубина исследования (1-5)
     * @param {number} reportData.breadth - Широта исследования (2-10)
     * @param {string} reportData.report_type - Тип отчёта ("report", "answer")
     * @returns {Promise<void>}
     */
    async generateAndDownloadReport(reportData) {
        try {
            const result = await this.generateReport(reportData);

            if (result && result.type === 'blob') {
                // Имя из ответа или сгенерированное
                const filename = result.filename || `research_report_${new Date().toISOString().replace(/[:.]/g, '-')}.pdf`;
                this.downloadFile(result.blob, filename);
                return { downloaded: true };
            }

            // Если пришло сообщение — вернуть его вызывающей стороне
            if (result && result.type === 'message') {
                return { downloaded: false, message: result.message };
            }

            // Неожиданный формат
            return { downloaded: false, message: 'Неизвестный ответ сервера' };
        } catch (error) {
            console.error('Ошибка при генерации и скачивании отчёта:', error);
            throw error;
        }
    }

    /**
     * Скачивает отчёт по ID
     * @param {string} reportId - ID отчёта
     * @returns {Promise<Blob>} - Файл отчёта
     */
    async downloadReport(reportId) {
        try {
            const response = await fetch(`${this.baseURL}${this.endpoints.DOWNLOAD}/${reportId}`, {
                method: 'GET',
                headers: {
                    Authorization: `Bearer ${this.getAuthToken()}`
                }
            });

            if (response.status === 404) {
                throw new Error('Отчёт не найден');
            }

            if (!response.ok) {
                const errorText = await response.text();
                throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
            }

            return await response.blob();
        } catch (error) {
            console.error('Ошибка при скачивании отчёта:', error);
            throw error;
        }
    }

    /**
     * Скачивает файл в браузере
     * @param {Blob} blob - Файл для скачивания
     * @param {string} filename - Имя файла
     */
    downloadFile(blob, filename) {
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
    }

    /**
     * Извлекает имя файла из заголовка Content-Disposition
     * @param {Response} response - HTTP ответ
     * @returns {string} - Имя файла
     */
    getFilenameFromResponse(response) {
        const contentDisposition = response.headers.get('Content-Disposition');
        if (contentDisposition) {
            const filenameMatch = contentDisposition.match(/filename="?([^"]+)"?/);
            return filenameMatch ? filenameMatch[1] : 'report.pdf';
        }
        return 'report.pdf';
    }

    /**
     * Форматирует размер файла в читаемый вид
     * @param {number} bytes - Размер в байтах
     * @returns {string} - Отформатированный размер
     */
    formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }

    /**
     * Получает токен авторизации из localStorage
     * @returns {string|null} - Токен авторизации
     */
    getAuthToken() {
        return localStorage.getItem('access_token');
    }

    /**
     * Обрабатывает ошибки API
     * @param {Error} error - Ошибка
     * @returns {string} - Сообщение об ошибке для пользователя
     */
    handleError(error) {
        if (error.message.includes('404')) {
            return 'Отчёт не найден';
        } else if (error.message.includes('400')) {
            return 'Некорректные параметры запроса';
        } else if (error.message.includes('401')) {
            return 'Необходима авторизация';
        } else if (error.message.includes('403')) {
            return 'Доступ запрещён';
        } else if (error.message.includes('500')) {
            return 'Внутренняя ошибка сервера';
        } else if (error.message.includes('504')) {
            return 'Таймаут при обращении к deep-research API. Попробуйте позже';
        } else {
            return 'Произошла ошибка: ' + error.message;
        }
    }
}

export default new ReportService();
