/**
 * @moduleName: Tour Modal Component - Interactive User Onboarding
 * @version: 1.0.0
 * @since: 2025-07-24
 * @lastUpdated: 2025-07-24
 * @projectSummary: MCP Quiz Server - Modal component for displaying interactive tour steps with navigation, videos, and progress tracking
 * @techStack: TypeScript, Component Architecture, DOM API, HTML5 Video
 * @dependency: Component base class, TourService, TourStep and TourState interfaces
 * @interModuleDependency: Component, TourService, tour state management
 * @requirementsTraceability:
 *   {@link Requirements.REQ_UI_005} (Interactive Tutorial & Onboarding System)
 * @briefDescription: Modal component that displays tour steps with content, videos, navigation buttons, and progress indicators
 * @methods: showStep, hide, render, bindEvents, updateProgress, handleVideoPlay
 * @contributors: Full Stack Wizard Mega Architect, GitHub Copilot
 * @examples: const tourModal = new TourModal(); tourModal.showStep(step, state);
 * @vulnerabilitiesAssessment: Video URL validation, DOM element sanitization, keyboard navigation support, escape key handling
 */

import { TourService, TourState, TourStep } from '../services/TourService';
import { DOMUtils } from '../utils/index';
import { Component } from './Component';

export class TourModal extends Component {
  private tourService: TourService;
  private currentStep: TourStep | null = null;
  private currentState: TourState | null = null;

  constructor() {
    super('#tour-modal');
    this.tourService = TourService.getInstance();
    this.tourService.setTourModal(this);
  }

  protected render(): void {
    // Modal is created in HTML, we just manage its content
  }

  protected bindEvents(): void {
    // Close modal on backdrop click
    this.element.addEventListener('click', e => {
      if (e.target === this.element) {
        this.tourService.skipTour();
      }
    });

    // Navigation buttons
    const prevBtn = this.element.querySelector('#tour-prev-btn');
    const nextBtn = this.element.querySelector('#tour-next-btn');
    const skipBtn = this.element.querySelector('#tour-skip-btn');
    const closeBtn = this.element.querySelector('#tour-close-btn');

    prevBtn?.addEventListener('click', () => {
      this.tourService.previousStep();
    });

    nextBtn?.addEventListener('click', () => {
      this.tourService.nextStep();
    });

    skipBtn?.addEventListener('click', () => {
      this.tourService.skipTour();
    });

    closeBtn?.addEventListener('click', () => {
      this.tourService.skipTour();
    });

    // Keyboard navigation
    document.addEventListener('keydown', this.handleKeydown.bind(this));

    // Video event handling
    const video = this.element.querySelector('#tour-video') as HTMLVideoElement;
    if (video) {
      video.addEventListener('ended', () => {
        // Auto-advance to next step when video ends (if enabled)
        const autoAdvance = this.element.querySelector('#auto-advance-toggle') as HTMLInputElement;
        if (autoAdvance?.checked && this.currentState?.canGoNext) {
          setTimeout(() => this.tourService.nextStep(), 1000);
        }
      });
    }
  }

  /**
   * @description Handles keyboard navigation for tour
   * @param {KeyboardEvent} e Keyboard event
   */
  private handleKeydown(e: KeyboardEvent): void {
    if (!this.currentState?.isActive) return;

    switch (e.key) {
      case 'Escape':
        this.tourService.skipTour();
        break;
      case 'ArrowLeft':
        if (this.currentState.canGoBack) {
          e.preventDefault();
          this.tourService.previousStep();
        }
        break;
      case 'ArrowRight':
      case 'Enter':
      case ' ':
        if (this.currentState.canGoNext) {
          e.preventDefault();
          this.tourService.nextStep();
        } else if (
          !this.currentState.canGoNext &&
          this.currentState.currentStep === this.currentState.totalSteps
        ) {
          e.preventDefault();
          this.tourService.completeTour();
        }
        break;
    }
  }

  /**
   * @description Shows a tour step in the modal
   * @param {TourStep} step Tour step to display
   * @param {TourState} state Current tour state
   */
  public showStep(step: TourStep, state: TourState): void {
    this.currentStep = step;
    this.currentState = state;

    // Update modal content
    this.updateContent(step);
    this.updateNavigation(state);
    this.updateProgress(state);

    // Show modal
    this.show();

    // // Handle video if present
    // if (step.video) {
    //   this.loadVideo(step.video);
    // }

    // Focus management for accessibility
    const nextBtn = this.element.querySelector('#tour-next-btn') as HTMLButtonElement;
    const skipBtn = this.element.querySelector('#tour-skip-btn') as HTMLButtonElement;
    (nextBtn || skipBtn)?.focus();
  }

  /**
   * @description Updates the modal content with step information
   * @param {TourStep} step Tour step data
   */
  private updateContent(step: TourStep): void {
    // Update title
    const title = this.element.querySelector('#tour-title');
    if (title) {
      title.textContent = step.title;
    }

    // Update content
    const content = this.element.querySelector('#tour-content');
    if (content) {
      content.innerHTML = DOMUtils.escapeHtml(step.content);
    }

    // Show/hide video section
    const videoSection = this.element.querySelector('#tour-video-section');
    const videoElement = this.element.querySelector('#tour-video') as HTMLVideoElement;

    if (step.video && videoSection) {
      videoSection.classList.remove('hidden');
      if (videoElement) {
        videoElement.src = step.video;
        videoElement.load();
      }
    } else if (videoSection) {
      videoSection.classList.add('hidden');
    }
  }

  /**
   * @description Updates navigation button states
   * @param {TourState} state Current tour state
   */
  private updateNavigation(state: TourState): void {
    const prevBtn = this.element.querySelector('#tour-prev-btn') as HTMLButtonElement;
    const nextBtn = this.element.querySelector('#tour-next-btn') as HTMLButtonElement;
    const skipBtn = this.element.querySelector('#tour-skip-btn') as HTMLButtonElement;

    if (prevBtn) {
      prevBtn.disabled = !state.canGoBack;
      prevBtn.classList.toggle('opacity-50', !state.canGoBack);
      prevBtn.classList.toggle('cursor-not-allowed', !state.canGoBack);
    }

    if (nextBtn) {
      nextBtn.disabled = !state.canGoNext;
      nextBtn.classList.toggle('opacity-50', !state.canGoNext);
      nextBtn.classList.toggle('cursor-not-allowed', !state.canGoNext);

      // Update next button text for last step
      if (state.currentStep === state.totalSteps) {
        nextBtn.textContent = 'Finish';
        nextBtn.classList.add('bg-green-600', 'hover:bg-green-700');
        nextBtn.classList.remove('bg-primary-600', 'hover:bg-primary-700');
      } else {
        nextBtn.textContent = 'Next';
        nextBtn.classList.remove('bg-green-600', 'hover:bg-green-700');
        nextBtn.classList.add('bg-primary-600', 'hover:bg-primary-700');
      }
    }

    if (skipBtn) {
      skipBtn.classList.toggle('hidden', !state.canSkip);
    }
  }

  /**
   * @description Updates the progress indicator
   * @param {TourState} state Current tour state
   */
  private updateProgress(state: TourState): void {
    // Update step counter
    const stepCounter = this.element.querySelector('#tour-step-counter');
    if (stepCounter) {
      stepCounter.textContent = `${state.currentStep} of ${state.totalSteps}`;
    }

    // Update progress bar
    const progressBar = this.element.querySelector('#tour-progress-bar') as HTMLElement;
    if (progressBar) {
      const percentage = (state.currentStep / state.totalSteps) * 100;
      progressBar.style.width = `${percentage}%`;
    }

    // Update progress dots
    const dots = this.element.querySelectorAll('.tour-progress-dot');
    dots.forEach((dot, index) => {
      if (index < state.currentStep) {
        dot.classList.add('bg-primary-600');
        dot.classList.remove('bg-surface-300');
      } else {
        dot.classList.remove('bg-primary-600');
        dot.classList.add('bg-surface-300');
      }
    });
  }

  /**
   * @description Loads and prepares video for playback
   * @param {string} videoUrl URL of the video to load
   */
  private loadVideo(videoUrl: string): void {
    const video = this.element.querySelector('#tour-video') as HTMLVideoElement;
    if (!video) return;

    video.src = videoUrl;
    video.load();

    // Add play button overlay
    const playButton = this.element.querySelector('#video-play-btn');
    if (playButton) {
      playButton.classList.remove('hidden');
      playButton.addEventListener('click', () => {
        video.play();
        playButton.classList.add('hidden');
      });
    }

    // Show video controls on first interaction
    video.addEventListener('play', () => {
      video.controls = true;
    });
  }

  /**
   * @description Shows the tour modal
   */
  public show(): void {
    this.element.classList.remove('hidden');
    this.element.classList.add('flex');

    // Add show animation
    setTimeout(() => {
      const content = this.element.querySelector('.modal-content');
      content?.classList.remove('translate-y-full', 'md:translate-y-0');
      content?.classList.add('translate-y-0');
    }, 10);

    // Prevent body scroll
    document.body.style.overflow = 'hidden';
  }

  /**
   * @description Hides the tour modal
   */
  public hide(): void {
    const content = this.element.querySelector('.modal-content');
    content?.classList.add('translate-y-full', 'md:translate-y-0');
    content?.classList.remove('translate-y-0');

    setTimeout(() => {
      this.element.classList.add('hidden');
      this.element.classList.remove('flex');

      // Restore body scroll
      document.body.style.overflow = '';

      // Reset video
      const video = this.element.querySelector('#tour-video') as HTMLVideoElement;
      if (video) {
        video.pause();
        video.currentTime = 0;
        video.removeAttribute('src');
      }
    }, 300);
  }

  /**
   * @description Gets the current step being displayed
   * @returns {TourStep | null} Current step or null
   */
  public getCurrentStep(): TourStep | null {
    return this.currentStep;
  }

  /**
   * @description Gets the current tour state
   * @returns {TourState | null} Current state or null
   */
  public getCurrentState(): TourState | null {
    return this.currentState;
  }
}
