// Main System Orchestrator - Ties together loading, setup, and initialization
class SystemOrchestrator {
  constructor() {
    this.systemLoader = null;
    this.loadingUI = null;
    this.setupDetector = null;
    this.isInitialized = false;
    this.loadingPromise = null;
  }

  // Initialize the entire system
  async initialize() {
    
    if (this.isInitialized) {
      return this.loadingPromise;
    }

    try {
      // Auth gate — must complete before anything else loads or fetches data
      if (window.authManager) {
        await window.authManager.initialize();
        window.authManager.interceptFetch();
      }


      // Initialize components
      this.systemLoader = new SystemLoader();
      
      this.loadingUI = new LoadingUI();
      
      this.setupDetector = new SetupDetector();

      // Show loading screen
      this.loadingUI.initialize();

      // Setup event listeners
      this.setupEventListeners();

      // Check if first-time setup is needed
      const setupStatus = await this.setupDetector.initialize();
      
      const hasActiveHandoff = (() => {
        try { return !!sessionStorage.getItem('libreportal_setup_handoff'); }
        catch { return false; }
      })();

      if (setupStatus.isFirstTime && !hasActiveHandoff) {
        await this.handleFirstTimeSetup();
      } else if (setupStatus.isFirstTime && hasActiveHandoff) {
        console.log('[orchestrator] setup handoff in progress, skipping wizard');
        await this.handleNormalLoading();
      } else {
        await this.handleNormalLoading();
      }

      this.isInitialized = true;

    } catch (error) {
      console.error('❌ System Orchestrator: Initialization failed:', error);
      this.handleInitializationError(error);
      throw error;
    }
  }

  // Setup event listeners
  setupEventListeners() {
    // System Loader events
    this.systemLoader.on('onProgress', (data) => {
      this.loadingUI.updateProgress(data.progress, `${data.checkName}...`);
      this.loadingUI.updateSystemCheck(
        data.systemId || this.getSystemIdFromCheck(data.checkId), // Use systemId if available, fallback to mapping
        data.checkName,
        data.status,
        data.error,
        data.message // Pass the message for tooltip
      );
    });

    this.systemLoader.on('onSystemCheck', (data) => {
      this.loadingUI.updateSystemCheck(
        data.systemId,
        data.checkName,
        data.status
      );
    });

    this.systemLoader.on('onComplete', (data) => {
      
      // Don't show errors here - let handleNormalLoading handle all error display logic
      if (data.success) {
        this.proceedToApplication();
      }
      // Errors will be handled in handleNormalLoading method
    });

    this.systemLoader.on('onError', (data) => {
      console.error('System Loader Error:', data);
    });

    // Override loading UI retry behavior
    this.loadingUI.onRetry = () => {
      this.retryInitialization();
    };
  }

  // Handle first-time setup
  async handleFirstTimeSetup() {
    
    return new Promise((resolve, reject) => {
      // Create and show setup wizard
      const setupWizard = new SetupWizard();
      setupWizard.initialize(this.setupDetector, async () => {
        try {
          // Setup completed, continue with normal loading
          await this.handleNormalLoading();
          resolve();
        } catch (error) {
          reject(error);
        }
      });
      
      setupWizard.show();
    });
  }

  // Handle normal loading sequence
  async handleNormalLoading() {
    
    // Wait longer for all scripts to fully load
    await new Promise(resolve => setTimeout(resolve, 2500));
    
    // Run health checks
    const results = await this.systemLoader.runHealthChecks();
    
    // Check for missing data files specifically
    const missingDataFiles = results.errors.filter(error => 
      error.error && (error.error.includes('Missing required data file') || 
                     error.error.includes('libreportal webui generate all ') ||
                     error.error.includes('Critical configuration files are missing or empty'))
    );
    
    if (missingDataFiles.length > 0) {
      console.warn('⚠️ Missing LibrePortal data files detected');
      
      // Show enhanced error message with setup instructions
      const enhancedErrors = results.errors.map(error => {
        if (error.error && (error.error.includes('Missing required data file') || 
                           error.error.includes('Critical configuration files are missing or empty'))) {
          return {
            ...error,
            error: `${error.error}\n\n🔧 TO FIX: Run this command in your terminal:\n   libreportal webui generate all \n\nThis will generate all required JSON files for the LibrePortal WebUI.`
          };
        }
        return error;
      });
      
      console.error('❌ Critical systems failed:', enhancedErrors);
      console.error('❌ Failed systems details:', JSON.stringify(enhancedErrors, null, 2));
      
      // Show enhanced errors in loading UI
      this.loadingUI.showError(enhancedErrors);
      
      // Listen for continue button click
      window.addEventListener('loadingContinue', () => {
        this.proceedToApplicationWithErrors();
      }, { once: true }); // Remove listener after first use
      this.errorAlreadyHandled = true;
      return; // Prevent reaching the general error handling below
    }
    
    if (results.success) {

      // Initialize all components (even if some health checks failed)
      await this.systemLoader.initializeComponents();

      // Hide loading screen only if everything is successful
      this.loadingUI.hide();

      // Now initialize the SPA after all components are ready
      this.initializeOriginalSPA();
      this.proceedToApplication();
    } else {
      console.error('❌ Critical systems failed:', results.errors);
      console.error('❌ Failed systems details:', JSON.stringify(results.errors, null, 2));
      
      // Show errors in loading UI and keep it visible (only if not already handled)
      if (!this.errorAlreadyHandled) {
        this.loadingUI.showError(results.errors);
      } else {
      }
      
      // Listen for continue button click
      window.addEventListener('loadingContinue', () => {
        this.proceedToApplicationWithErrors();
      }, { once: true }); // Remove listener after first use
    }
  }

  // Proceed to main application
  proceedToApplication() {
    
    // Don't initialize SPA here - wait for component initialization to complete
    // SPA will be initialized after all components are ready
  }

  // Proceed with application despite errors (user choice)
  async proceedToApplicationWithErrors() {
    
    // Initialize components even though some checks failed
    await this.systemLoader.initializeComponents();
    
    // Hide loading screen and proceed
    this.loadingUI.hide();

    // Now initialize the SPA after all components are ready
    this.initializeOriginalSPA();

    this.proceedToApplication();
  }

  // Initialize the original SPA system
  initializeOriginalSPA() {
    
    if (typeof window.spaClean !== 'undefined') {
      
      // Now manually call the SPA's init method since we prevented auto-initialization
      if (typeof window.spaClean.init === 'function') {
        window.spaClean.init().then(() => {
        }).catch(error => {
          console.error('❌ SPA initialization failed:', error);
        });
      }
      
    } else if (typeof LibrePortalSPAClean !== 'undefined') {
      window.spaClean = new LibrePortalSPAClean();
    } else {
      console.error('❌ SPA class not available');
      return;
    }
  }

  // Handle initialization errors
  handleInitializationError(error) {
    console.error('❌ Critical initialization error:', error);
    
    // Show error in loading UI
    this.loadingUI.showError([{
      system: 'System Orchestrator',
      check: 'Initialization',
      error: error.message
    }]);

    // Show retry button
    const retryButton = document.getElementById('retry-button');
    if (retryButton) {
      retryButton.style.display = 'inline-block';
    }
  }

  // Retry initialization
  async retryInitialization() {
    
    // Reset UI
    this.loadingUI.reset();
    
    // Reset state
    this.isInitialized = false;
    this.loadingPromise = null;
    
    // Try again
    await this.initialize();
  }

  // Get system ID from check ID
  getSystemIdFromCheck(checkId) {
    // Map check IDs to system IDs
    const checkToSystemMap = {
      'dom': 'core',
      'spa': 'core',
      'utils': 'core',
      'data-loader': 'core',
      'config-files': 'config-validation', // Fixed: moved to config-validation system
      'update-lock': 'update-lock', // Update Lock check
      'pause-lock': 'pause-lock', // Pause Lock check
      'system-locks-combined': 'system-locks', // System Locks check
      'apps-data': 'data',
      'categories-data': 'data',
      'config-data': 'data',
      'topbar': 'components',
      'notifications': 'components',
      'task-manager': 'task',
      'apps-manager': 'managers',
      'config-manager': 'managers',
      'app-tabbed-manager': 'managers',
      'server-connectivity': 'backend',
      'api-endpoints': 'backend'
    };

    return checkToSystemMap[checkId] || 'core';
  }

  // Get current status
  getStatus() {
    return {
      initialized: this.isInitialized,
      loading: this.loadingPromise !== null && !this.isInitialized,
      setup: this.setupDetector?.getSetupStatus(),
      systemSummary: this.systemLoader?.getSystemSummary()
    };
  }

  // Force re-initialization (for testing)
  async forceReinitialize() {
    
    // Clean up
    if (this.loadingUI && this.loadingUI.isVisible) {
      this.loadingUI.hide();
    }
    
    // Reset state
    this.isInitialized = false;
    this.loadingPromise = null;
    
    // Re-initialize
    await this.initialize();
  }
}

// Global instance and initialization
window.SystemOrchestrator = SystemOrchestrator;

// Auto-initialize when DOM is ready
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', async () => {
    window.systemOrchestrator = new SystemOrchestrator();
    await window.systemOrchestrator.initialize();
  });
} else {
  // DOM already ready
  (async () => {
    window.systemOrchestrator = new SystemOrchestrator();
    await window.systemOrchestrator.initialize();
  })();
}
