/**
 * Client-Side Error Reporter
 *
 * Automatically captures and reports JavaScript errors during file uploads
 * to help diagnose issues during beta testing.
 */

class ErrorReporter {
    constructor() {
        this.uploadId = null;
        this.errorQueue = [];
        this.reportEndpoint = '/api/v1/captures/report_client_error';

        // Setup global error handler
        this.setupGlobalErrorHandler();
    }

    /**
     * Set current upload ID for error tracking
     */
    setUploadId(uploadId) {
        this.uploadId = uploadId;
        console.log(`[ErrorReporter] Tracking upload: ${uploadId}`);
    }

    /**
     * Setup global error handlers
     */
    setupGlobalErrorHandler() {
        // Catch unhandled JavaScript errors
        window.addEventListener('error', (event) => {
            this.reportError({
                error_type: event.error?.name || 'Error',
                error_message: event.message,
                stack_trace: event.error?.stack,
                filename: event.filename,
                lineno: event.lineno,
                colno: event.colno,
                source: 'window.error'
            });
        });

        // Catch unhandled promise rejections
        window.addEventListener('unhandledrejection', (event) => {
            this.reportError({
                error_type: 'UnhandledPromiseRejection',
                error_message: event.reason?.message || String(event.reason),
                stack_trace: event.reason?.stack,
                source: 'unhandledrejection'
            });
        });
    }

    /**
     * Report error to server
     */
    async reportError(errorData) {
        const errorReport = {
            upload_id: this.uploadId || 'no_upload_id',
            timestamp: new Date().toISOString(),
            ...errorData,
            browser_info: this.getBrowserInfo(),
            page_url: window.location.href
        };

        // Log to console
        console.error('[ErrorReporter] Reporting error:', errorReport);

        // Queue error (in case of network issues)
        this.errorQueue.push(errorReport);

        // Try to send immediately
        try {
            await this.sendErrorReport(errorReport);
            // Remove from queue if successful
            this.errorQueue = this.errorQueue.filter(e => e !== errorReport);
        } catch (e) {
            console.warn('[ErrorReporter] Failed to send error report:', e);
            // Will retry later
        }
    }

    /**
     * Send error report to server
     */
    async sendErrorReport(errorReport) {
        const response = await fetch(this.reportEndpoint, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(errorReport)
        });

        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }

        return response.json();
    }

    /**
     * Report parse error specifically
     */
    reportParseError(filename, error, fileContentSample = '') {
        this.reportError({
            error_type: 'SubFileParseError',
            error_message: error.message || String(error),
            stack_trace: error.stack,
            filename: filename,
            file_content_sample: fileContentSample.substring(0, 500),
            source: 'sub_parser'
        });
    }

    /**
     * Report upload error
     */
    reportUploadError(filename, error, stage = 'unknown') {
        this.reportError({
            error_type: 'UploadError',
            error_message: error.message || String(error),
            stack_trace: error.stack,
            filename: filename,
            upload_stage: stage,
            source: 'upload_handler'
        });
    }

    /**
     * Report validation error
     */
    reportValidationError(field, value, reason) {
        this.reportError({
            error_type: 'ValidationError',
            error_message: `${field} validation failed: ${reason}`,
            validation_field: field,
            validation_value: String(value),
            source: 'validation'
        });
    }

    /**
     * Report network error
     */
    reportNetworkError(url, status, statusText) {
        this.reportError({
            error_type: 'NetworkError',
            error_message: `${status} ${statusText}`,
            request_url: url,
            http_status: status,
            source: 'network'
        });
    }

    /**
     * Get browser information
     */
    getBrowserInfo() {
        return {
            user_agent: navigator.userAgent,
            platform: navigator.platform,
            language: navigator.language,
            screen_width: screen.width,
            screen_height: screen.height,
            viewport_width: window.innerWidth,
            viewport_height: window.innerHeight,
            connection_type: navigator.connection?.effectiveType,
            device_memory: navigator.deviceMemory,
            hardware_concurrency: navigator.hardwareConcurrency,
            online: navigator.onLine
        };
    }

    /**
     * Flush error queue (send all pending errors)
     */
    async flushErrorQueue() {
        const pending = [...this.errorQueue];
        this.errorQueue = [];

        for (const error of pending) {
            try {
                await this.sendErrorReport(error);
            } catch (e) {
                // If still fails, put back in queue
                this.errorQueue.push(error);
            }
        }

        return {
            sent: pending.length - this.errorQueue.length,
            failed: this.errorQueue.length
        };
    }

    /**
     * Generate upload ID
     */
    generateUploadId() {
        const timestamp = new Date().toISOString().replace(/[-:]/g, '').replace('T', '_').substring(0, 15);
        const random = Math.random().toString(36).substring(2, 10);
        return `upload_${timestamp}_${random}`;
    }
}

// Create global instance
window.errorReporter = new ErrorReporter();

// Export for module use
if (typeof module !== 'undefined' && module.exports) {
    module.exports = ErrorReporter;
}
