/**
 * Error Handler
 * Handles errors gracefully without breaking the onboarding tour
 */

(function(window) {
  'use strict';

  class ErrorHandler {
    constructor() {
      this.errors = [];
      this.maxErrors = 50; // Keep last 50 errors
    }

    /**
     * Log an error without breaking the tour
     * @param {string} context - Context where error occurred
     * @param {Error|string} error - The error object or message
     * @param {Object} metadata - Additional metadata
     */
    logError(context, error, metadata = {}) {
      const errorEntry = {
        timestamp: new Date().toISOString(),
        context,
        message: error instanceof Error ? error.message : error,
        stack: error instanceof Error ? error.stack : null,
        metadata
      };

      // Add to errors array
      this.errors.push(errorEntry);

      // Keep only last maxErrors
      if (this.errors.length > this.maxErrors) {
        this.errors.shift();
      }

      // Log to console
      console.error(`[Onboarding Error] ${context}:`, error, metadata);

      // Optionally send to error tracking service
      // this.sendToErrorTracking(errorEntry);
    }

    /**
     * Attempt to recover from an error and continue tour
     * @param {Error} error - The error object
     * @param {number} currentStep - Current step index
     * @returns {Object} Recovery action
     */
    recoverFromError(error, currentStep) {
      const errorType = this.classifyError(error);

      switch (errorType) {
        case 'ELEMENT_NOT_FOUND':
          this.logError('Element Not Found', error, { currentStep });
          return { 
            action: 'SKIP_STEP', 
            nextStep: currentStep + 1,
            message: 'Target element not found, skipping to next step'
          };

        case 'STORAGE_UNAVAILABLE':
          this.logError('Storage Unavailable', error);
          return { 
            action: 'USE_MEMORY_STORAGE',
            message: 'Local storage unavailable, using in-memory storage'
          };

        case 'DRIVER_NOT_LOADED':
          this.logError('Driver.js Not Loaded', error);
          return {
            action: 'ABORT_TOUR',
            message: 'Driver.js library not loaded, cannot start tour'
          };

        case 'INVALID_TOOLTIP':
          this.logError('Invalid Tooltip Configuration', error, { currentStep });
          return {
            action: 'SKIP_STEP',
            nextStep: currentStep + 1,
            message: 'Invalid tooltip configuration, skipping'
          };

        case 'THEME_DETECTION_FAILED':
          this.logError('Theme Detection Failed', error);
          return {
            action: 'USE_DEFAULT_THEME',
            message: 'Using default dark theme'
          };

        default:
          this.logError('Unknown Error', error, { currentStep });
          return {
            action: 'ABORT_TOUR',
            message: 'Unexpected error occurred, aborting tour'
          };
      }
    }

    /**
     * Classify error type
     * @private
     * @param {Error} error - The error object
     * @returns {string} Error type
     */
    classifyError(error) {
      const message = error.message || error.toString();

      if (message.includes('element') && message.includes('not found')) {
        return 'ELEMENT_NOT_FOUND';
      }
      if (message.includes('storage') || message.includes('quota')) {
        return 'STORAGE_UNAVAILABLE';
      }
      if (message.includes('driver') || message.includes('undefined')) {
        return 'DRIVER_NOT_LOADED';
      }
      if (message.includes('invalid') || message.includes('validation')) {
        return 'INVALID_TOOLTIP';
      }
      if (message.includes('theme')) {
        return 'THEME_DETECTION_FAILED';
      }

      return 'UNKNOWN';
    }

    /**
     * Get all logged errors
     * @returns {Array} Array of error entries
     */
    getErrors() {
      return [...this.errors];
    }

    /**
     * Clear all logged errors
     */
    clearErrors() {
      this.errors = [];
    }

    /**
     * Get error statistics
     * @returns {Object} Error statistics
     */
    getStatistics() {
      const stats = {
        total: this.errors.length,
        byContext: {},
        byType: {},
        recent: this.errors.slice(-10)
      };

      this.errors.forEach(error => {
        // Count by context
        stats.byContext[error.context] = (stats.byContext[error.context] || 0) + 1;

        // Count by type
        const type = this.classifyError({ message: error.message });
        stats.byType[type] = (stats.byType[type] || 0) + 1;
      });

      return stats;
    }

    /**
     * Handle graceful degradation when Driver.js fails to load
     * @returns {boolean} Whether fallback was successful
     */
    handleDriverLoadFailure() {
      this.logError('Driver.js Load Failure', 'Driver.js library failed to load');

      // Show fallback message
      const fallbackMessage = document.createElement('div');
      fallbackMessage.id = 'onboarding-fallback';
      fallbackMessage.style.cssText = `
        position: fixed;
        bottom: 20px;
        right: 20px;
        background: var(--card-base, #2a2a2a);
        color: var(--fg, #ffffff);
        padding: 15px 20px;
        border-radius: 8px;
        box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        z-index: 9999;
        max-width: 300px;
        font-size: 14px;
      `;
      fallbackMessage.innerHTML = `
        <strong>Welcome to DashCaddy!</strong><br>
        <p style="margin: 10px 0 0 0; font-size: 12px;">
          The interactive tour is unavailable, but you can explore the dashboard freely.
          Check the documentation for help getting started.
        </p>
      `;

      document.body.appendChild(fallbackMessage);

      // Auto-remove after 10 seconds
      setTimeout(() => {
        if (fallbackMessage.parentNode) {
          fallbackMessage.parentNode.removeChild(fallbackMessage);
        }
      }, 10000);

      return true;
    }

    /**
     * Handle storage unavailable scenario
     * @returns {Object} In-memory storage fallback
     */
    handleStorageUnavailable() {
      this.logError('Storage Unavailable', 'Local storage is not available');

      // Create in-memory storage
      const memoryStorage = {
        data: {},
        getItem(key) {
          return this.data[key] || null;
        },
        setItem(key, value) {
          this.data[key] = value;
        },
        removeItem(key) {
          delete this.data[key];
        },
        clear() {
          this.data = {};
        }
      };

      console.warn('[ErrorHandler] Using in-memory storage - progress will not persist');
      return memoryStorage;
    }

    /**
     * Send error to tracking service (placeholder)
     * @private
     * @param {Object} errorEntry - Error entry to send
     */
    sendToErrorTracking(errorEntry) {
      // Placeholder for error tracking integration
      // Could integrate with Sentry, LogRocket, etc.
      // Example:
      // if (window.Sentry) {
      //   Sentry.captureException(new Error(errorEntry.message), {
      //     extra: errorEntry.metadata
      //   });
      // }
    }
  }

  window.ErrorHandler = ErrorHandler;
  console.log('[ErrorHandler] Module loaded');

})(window);
