/**
 * @moduleName: Tour Service - In-App User Onboarding System
 * @version: 1.0.0
 * @since: 2025-07-24
 * @lastUpdated: 2025-07-24
 * @projectSummary: MCP Quiz Server - Interactive tour system for user onboarding with spotlight effects and progressive disclosure
 * @techStack: TypeScript, DOM API, LocalStorage, Component Architecture
 * @dependency: Component system, localStorage
 * @interModuleDependency: TourModal, existing UI components
 * @requirementsTraceability:
 *   {@link Requirements.REQ_UI_005} (Interactive Tutorial & Onboarding System)
 * @briefDescription: Service managing interactive tours with spotlight highlighting, step navigation, progress tracking, and persistent completion state
 * @methods: startTour, nextStep, previousStep, skipTour, completeTour, highlightElement
 * @contributors: Full Stack Wizard Mega Architect, GitHub Copilot
 * @examples: TourService.getInstance().startTour('welcome'); // Start welcome tour
 * @vulnerabilitiesAssessment: DOM element validation prevents errors, localStorage prevents tour spam, proper cleanup prevents memory leaks
 */

export interface TourStep {
  id: string;
  title: string;
  content: string;
  target?: string; // CSS selector for element to highlight
  position: 'top' | 'bottom' | 'left' | 'right' | 'center';
  showSkip: boolean;
  showPrevious: boolean;
  showNext: boolean;
  action?: () => void; // Optional action to perform
  video?: string; // Optional video URL from Playwright demos
}

export interface Tour {
  id: string;
  name: string;
  description: string;
  steps: TourStep[];
  autoStart: boolean;
  showOnFirstVisit: boolean;
}

export interface TourState {
  isActive: boolean;
  currentTour: string | null;
  currentStep: number;
  totalSteps: number;
  canGoBack: boolean;
  canGoNext: boolean;
  canSkip: boolean;
}

export class TourService {
  private static instance: TourService;
  private tours: Map<string, Tour> = new Map();
  private currentTour: Tour | null = null;
  private currentStepIndex: number = 0;
  private tourModal: any = null; // Will be set by TourModal component
  private overlay: HTMLElement | null = null;
  private spotlight: HTMLElement | null = null;
  private callbacks: Array<(state: TourState) => void> = [];

  private constructor() {
    this.initializeTours();
    this.createOverlayElements();
  }

  /**
   * @description Gets singleton instance of TourService
   * @returns {TourService} Singleton instance
   */
  public static getInstance(): TourService {
    if (!TourService.instance) {
      TourService.instance = new TourService();
    }
    return TourService.instance;
  }

  /**
   * @description Initializes default tour configurations
   */
  private initializeTours(): void {
    // Welcome Tour - First time user experience
    this.registerTour({
      id: 'welcome',
      name: 'Welcome to Quiz Server',
      description: 'Quick introduction to the quiz application',
      autoStart: true,
      showOnFirstVisit: true,
      steps: [
        {
          id: 'welcome',
          title: '🎉 Welcome to Quiz Server!',
          content:
            'Take interactive quizzes with real-time feedback. This quick tour will show you the key features.',
          position: 'center',
          showSkip: true,
          showPrevious: false,
          showNext: true,
          video: '/demos/welcome-overview.webm',
        },
        {
          id: 'quiz-list',
          title: '📋 Quiz Library',
          content: 'Browse available quizzes by category and difficulty. Click any quiz to start!',
          target: '#quiz-list',
          position: 'right',
          showSkip: true,
          showPrevious: true,
          showNext: true,
        },
        {
          id: 'settings',
          title: '⚙️ Customize Experience',
          content:
            'Access settings to personalize your quiz experience - themes, timer, navigation preferences.',
          target: '[data-tour="settings-button"]',
          position: 'bottom',
          showSkip: true,
          showPrevious: true,
          showNext: true,
          action: () => {
            // Briefly highlight settings button
            const settingsBtn = document.querySelector('[data-tour="settings-button"]');
            settingsBtn?.classList.add('tour-pulse');
            setTimeout(() => settingsBtn?.classList.remove('tour-pulse'), 2000);
          },
        },
        {
          id: 'timer',
          title: '⏱️ Quiz Timer',
          content:
            'Enable the timer for timed quizzes. Perfect for practice sessions and competitive challenges.',
          target: '#timer-toggle',
          position: 'left',
          showSkip: true,
          showPrevious: true,
          showNext: true,
        },
        {
          id: 'ready',
          title: "🚀 You're All Set!",
          content: 'Ready to test your knowledge? Pick a quiz from the sidebar and start learning!',
          position: 'center',
          showSkip: false,
          showPrevious: true,
          showNext: false,
        },
      ],
    });

    // Quick Features Tour - For returning users
    this.registerTour({
      id: 'features',
      name: 'Key Features Tour',
      description: 'Overview of main application features',
      autoStart: false,
      showOnFirstVisit: false,
      steps: [
        {
          id: 'navigation',
          title: '🧭 Smart Navigation',
          content: 'Use Previous/Next buttons or keyboard arrows to navigate through questions.',
          target: '.nav-buttons',
          position: 'bottom',
          showSkip: true,
          showPrevious: false,
          showNext: true,
        },
        {
          id: 'view-modes',
          title: '👁️ View Modes',
          content: 'Switch between single question focus or see all questions at once.',
          target: '[data-tour="view-toggle"]',
          position: 'top',
          showSkip: true,
          showPrevious: true,
          showNext: false,
        },
      ],
    });
  }

  /**
   * @description Creates overlay elements for spotlight effects
   */
  private createOverlayElements(): void {
    // Create tour overlay
    this.overlay = document.createElement('div');
    this.overlay.id = 'tour-overlay';
    this.overlay.className = 'tour-overlay hidden';

    // Create spotlight element
    this.spotlight = document.createElement('div');
    this.spotlight.id = 'tour-spotlight';
    this.spotlight.className = 'tour-spotlight';

    document.body.appendChild(this.overlay);
    document.body.appendChild(this.spotlight);
  }

  /**
   * @description Registers a new tour configuration
   * @param {Tour} tour Tour configuration object
   */
  public registerTour(tour: Tour): void {
    this.tours.set(tour.id, tour);
  }

  /**
   * @description Starts a tour by ID
   * @param {string} tourId Tour identifier
   * @returns {boolean} True if tour started successfully
   */
  public startTour(tourId: string): boolean {
    // Don't start tours if disabled
    if (this.isToursDisabled()) {
      return false;
    }

    const tour = this.tours.get(tourId);
    if (!tour || this.hasCompletedTour(tourId)) {
      return false;
    }

    this.currentTour = tour;
    this.currentStepIndex = 0;
    this.showStep(0);
    this.notifySubscribers();

    return true;
  }

  /**
   * @description Shows a specific step in the current tour
   * @param {number} stepIndex Step index to show
   */
  private showStep(stepIndex: number): void {
    if (!this.currentTour || stepIndex < 0 || stepIndex >= this.currentTour.steps.length) {
      return;
    }

    const step = this.currentTour.steps[stepIndex];
    this.currentStepIndex = stepIndex;

    // Show overlay
    this.overlay?.classList.remove('hidden');

    // Handle spotlight
    if (step.target) {
      this.highlightElement(step.target);
    } else {
      this.hideSpotlight();
    }

    // Execute step action
    if (step.action) {
      step.action();
    }

    // Update modal content (will be handled by TourModal component)
    if (this.tourModal) {
      this.tourModal.showStep(step, this.getTourState());
    }
  }

  /**
   * @description Highlights a DOM element with spotlight effect
   * @param {string} selector CSS selector for element to highlight
   */
  private highlightElement(selector: string): void {
    const element = document.querySelector(selector) as HTMLElement;
    if (!element || !this.spotlight) return;

    const rect = element.getBoundingClientRect();
    const padding = 8;

    this.spotlight.style.top = `${rect.top - padding}px`;
    this.spotlight.style.left = `${rect.left - padding}px`;
    this.spotlight.style.width = `${rect.width + padding * 2}px`;
    this.spotlight.style.height = `${rect.height + padding * 2}px`;
    this.spotlight.classList.remove('hidden');

    // Add highlight class to element
    element.classList.add('tour-highlighted');

    // Remove highlight after step transition
    setTimeout(() => {
      element.classList.remove('tour-highlighted');
    }, 3000);
  }

  /**
   * @description Hides the spotlight effect
   */
  private hideSpotlight(): void {
    this.spotlight?.classList.add('hidden');
  }

  /**
   * @description Advances to the next tour step
   * @returns {boolean} True if advanced successfully
   */
  public nextStep(): boolean {
    if (!this.currentTour || this.currentStepIndex >= this.currentTour.steps.length - 1) {
      this.completeTour();
      return false;
    }

    this.showStep(this.currentStepIndex + 1);
    this.notifySubscribers();
    return true;
  }

  /**
   * @description Goes back to the previous tour step
   * @returns {boolean} True if went back successfully
   */
  public previousStep(): boolean {
    if (!this.currentTour || this.currentStepIndex <= 0) {
      return false;
    }

    this.showStep(this.currentStepIndex - 1);
    this.notifySubscribers();
    return true;
  }

  /**
   * @description Skips the current tour
   */
  public skipTour(): void {
    this.endTour(false);
  }

  /**
   * @description Completes the current tour
   */
  public completeTour(): void {
    this.endTour(true);
  }

  /**
   * @description Ends the current tour
   * @param {boolean} completed Whether tour was completed or skipped
   */
  private endTour(completed: boolean): void {
    if (!this.currentTour) return;

    // Save completion state
    if (completed) {
      this.markTourAsCompleted(this.currentTour.id);
    }

    // Hide UI elements
    this.overlay?.classList.add('hidden');
    this.hideSpotlight();

    // Clear state
    this.currentTour = null;
    this.currentStepIndex = 0;

    // Close modal
    if (this.tourModal) {
      this.tourModal.hide();
    }

    this.notifySubscribers();
  }

  /**
   * @description Checks if user should see tour on first visit
   * @returns {boolean} True if should show welcome tour
   */
  public shouldShowWelcomeTour(): boolean {
    // Check for programmatic tour disable flag
    if (this.isToursDisabled()) {
      return false;
    }
    return !this.hasCompletedTour('welcome') && !this.hasSeenApp();
  }

  /**
   * @description Checks if tours are disabled via environment or programmatic flag
   * @returns {boolean} True if tours should be disabled
   */
  private isToursDisabled(): boolean {
    // Check localStorage flag for programmatic disable
    if (localStorage.getItem('disable-tours') === 'true') {
      return true;
    }

    // Check for testing environment indicators
    if (
      typeof window !== 'undefined' &&
      ((window as any).__PLAYWRIGHT__ ||
        (window as any).__TEST_MODE__ ||
        navigator.webdriver ||
        (window as any).Cypress)
    ) {
      return true;
    }

    return false;
  }

  /**
   * @description Checks if tour has been completed
   * @param {string} tourId Tour identifier
   * @returns {boolean} True if completed
   */
  private hasCompletedTour(tourId: string): boolean {
    const completed = localStorage.getItem(`tour-completed-${tourId}`);
    return completed === 'true';
  }

  /**
   * @description Marks tour as completed in localStorage
   * @param {string} tourId Tour identifier
   */
  private markTourAsCompleted(tourId: string): void {
    localStorage.setItem(`tour-completed-${tourId}`, 'true');
    localStorage.setItem('app-first-visit', 'false');
  }

  /**
   * @description Checks if user has seen the app before
   * @returns {boolean} True if not first visit
   */
  private hasSeenApp(): boolean {
    return localStorage.getItem('app-first-visit') === 'false';
  }

  /**
   * @description Gets current tour state
   * @returns {TourState} Current state object
   */
  public getTourState(): TourState {
    if (!this.currentTour) {
      return {
        isActive: false,
        currentTour: null,
        currentStep: 0,
        totalSteps: 0,
        canGoBack: false,
        canGoNext: false,
        canSkip: false,
      };
    }

    const step = this.currentTour.steps[this.currentStepIndex];
    return {
      isActive: true,
      currentTour: this.currentTour.id,
      currentStep: this.currentStepIndex + 1,
      totalSteps: this.currentTour.steps.length,
      canGoBack: step.showPrevious && this.currentStepIndex > 0,
      canGoNext: step.showNext && this.currentStepIndex < this.currentTour.steps.length - 1,
      canSkip: step.showSkip,
    };
  }

  /**
   * @description Subscribes to tour state changes
   * @param {function} callback Function to call on state change
   * @returns {function} Unsubscribe function
   */
  public subscribe(callback: (state: TourState) => void): () => void {
    this.callbacks.push(callback);
    return () => {
      const index = this.callbacks.indexOf(callback);
      if (index > -1) {
        this.callbacks.splice(index, 1);
      }
    };
  }

  /**
   * @description Notifies all subscribers of state changes
   */
  private notifySubscribers(): void {
    const state = this.getTourState();
    this.callbacks.forEach(callback => {
      try {
        callback(state);
      } catch (error) {
        console.error('Error in tour state callback:', error);
      }
    });
  }

  /**
   * @description Sets the tour modal component reference
   * @param {any} modal TourModal component instance
   */
  public setTourModal(modal: any): void {
    this.tourModal = modal;
  }

  /**
   * @description Gets list of available tours
   * @returns {Tour[]} Array of available tours
   */
  public getAvailableTours(): Tour[] {
    return Array.from(this.tours.values());
  }

  /**
   * @description Resets tour completion state (for testing)
   */
  public resetTourProgress(): void {
    this.tours.forEach((_, tourId) => {
      localStorage.removeItem(`tour-completed-${tourId}`);
    });
    localStorage.removeItem('app-first-visit');
  }
}

// Export singleton instance
export const tourService = TourService.getInstance();
