import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEncapsulation, ViewChild, ElementRef, OnDestroy, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';

export type VideoPlayerSize = 'sm' | 'md' | 'lg';
export type VideoPlayerVariant = 'default' | 'minimal' | 'theater';
export type VideoQuality = '240p' | '360p' | '480p' | '720p' | '1080p' | 'auto';

export interface VideoSource {
  src: string;
  type: string;
  quality?: VideoQuality;
  label?: string;
}

export interface VideoTrack {
  src: string;
  kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata';
  srclang: string;
  label: string;
  default?: boolean;
}

@Component({
  selector: 'ui-video-player',
  standalone: true,
  imports: [CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  template: `
    <div 
      class="ui-video-player"
      [class]="getComponentClasses()"
      [attr.aria-label]="ariaLabel">
      
      <!-- Video element -->
      <div class="ui-video-player__video-container">
        <video
          #videoElement
          class="ui-video-player__video"
          [poster]="poster"
          [muted]="muted"
          [autoplay]="autoplay"
          [loop]="loop"
          [attr.playsinline]="playsinline"
          [preload]="preload"
          [attr.aria-label]="videoAriaLabel"
          (loadstart)="handleLoadStart()"
          (loadeddata)="handleLoadedData()"
          (canplay)="handleCanPlay()"
          (play)="handlePlay()"
          (pause)="handlePause()"
          (ended)="handleEnded()"
          (timeupdate)="handleTimeUpdate()"
          (volumechange)="handleVideoVolumeChange()"
          (error)="handleError($event)">
          
          <!-- Video sources -->
          @for (source of sources; track source.src) {
            <source [src]="source.src" [type]="source.type">
          }
          
          <!-- Text tracks -->
          @for (track of tracks; track track.src) {
            <track 
              [src]="track.src" 
              [kind]="track.kind" 
              [srclang]="track.srclang" 
              [label]="track.label"
              [default]="track.default || false">
          }
          
          <!-- Fallback message -->
          <p class="ui-video-player__fallback">
            Your browser does not support the video tag.
            @if (sources.length > 0) {
              <a [href]="sources[0].src" target="_blank">Download the video</a>
            }
          </p>
        </video>
        
        <!-- Loading overlay -->
        @if (loading()) {
          <div class="ui-video-player__loading-overlay">
            <div class="ui-video-player__loading-spinner"></div>
            <span class="ui-video-player__loading-text">Loading video...</span>
          </div>
        }
        
        <!-- Controls overlay -->
        @if (showControls && !disabled) {
          <div class="ui-video-player__controls" [class.ui-video-player__controls--visible]="controlsVisible()">
            
            <!-- Play/Pause button -->
            <button 
              class="ui-video-player__control ui-video-player__play-pause"
              [disabled]="disabled || loading"
              (click)="togglePlayPause()"
              [attr.aria-label]="isPlaying() ? 'Pause video' : 'Play video'"
              type="button">
              @if (isPlaying()) {
                <svg class="ui-video-player__control-icon" viewBox="0 0 24 24" fill="currentColor">
                  <rect x="6" y="4" width="4" height="16"/>
                  <rect x="14" y="4" width="4" height="16"/>
                </svg>
              } @else {
                <svg class="ui-video-player__control-icon" viewBox="0 0 24 24" fill="currentColor">
                  <polygon points="5,3 19,12 5,21"/>
                </svg>
              }
            </button>
            
            <!-- Progress bar -->
            <div class="ui-video-player__progress-container">
              <input 
                type="range"
                class="ui-video-player__progress-bar"
                [min]="0"
                [max]="duration() || 100"
                [value]="currentTime()"
                [disabled]="disabled || loading"
                (input)="handleSeek($event)"
                [attr.aria-label]="'Seek video position'"
                step="0.1">
              <div class="ui-video-player__progress-track">
                <div class="ui-video-player__progress-filled" [style.width.%]="progressPercentage()"></div>
              </div>
            </div>
            
            <!-- Time display -->
            <span class="ui-video-player__time">
              {{ formatTime(currentTime()) }} / {{ formatTime(duration()) }}
            </span>
            
            <!-- Volume control -->
            @if (showVolumeControl) {
              <button 
                class="ui-video-player__control ui-video-player__mute"
                [disabled]="disabled"
                (click)="toggleMute()"
                [attr.aria-label]="isMuted() ? 'Unmute video' : 'Mute video'"
                type="button">
                @if (isMuted() || volume() === 0) {
                  <svg class="ui-video-player__control-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <polygon points="11,5 6,9 2,9 2,15 6,15 11,19"/>
                    <line x1="23" y1="9" x2="17" y2="15"/>
                    <line x1="17" y1="9" x2="23" y2="15"/>
                  </svg>
                } @else if (volume() < 0.5) {
                  <svg class="ui-video-player__control-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <polygon points="11,5 6,9 2,9 2,15 6,15 11,19"/>
                    <path d="M15.54,8.46a5,5,0,0,1,0,7.07"/>
                  </svg>
                } @else {
                  <svg class="ui-video-player__control-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <polygon points="11,5 6,9 2,9 2,15 6,15 11,19"/>
                    <path d="M19.07,4.93a10,10,0,0,1,0,14.14M15.54,8.46a5,5,0,0,1,0,7.07"/>
                  </svg>
                }
              </button>
              
              <input 
                type="range"
                class="ui-video-player__volume-bar"
                [min]="0"
                [max]="1"
                [value]="volume()"
                [disabled]="disabled"
                (input)="handleVolumeSliderChange($event)"
                [attr.aria-label]="'Volume control'"
                step="0.1">
            }
            
            <!-- Fullscreen button -->
            @if (allowFullscreen) {
              <button 
                class="ui-video-player__control ui-video-player__fullscreen"
                [disabled]="disabled"
                (click)="toggleFullscreen()"
                [attr.aria-label]="isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'"
                type="button">
                @if (isFullscreen()) {
                  <svg class="ui-video-player__control-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/>
                  </svg>
                } @else {
                  <svg class="ui-video-player__control-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
                  </svg>
                }
              </button>
            }
          </div>
        }
      </div>
      
      <!-- Error message -->
      @if (hasError()) {
        <div class="ui-video-player__error">
          <div class="ui-video-player__error-icon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <circle cx="12" cy="12" r="10"/>
              <line x1="12" y1="8" x2="12" y2="12"/>
              <line x1="12" y1="16" x2="12.01" y2="16"/>
            </svg>
          </div>
          <p class="ui-video-player__error-message">{{ errorMessage() || 'Failed to load video' }}</p>
          @if (sources.length > 0) {
            <a [href]="sources[0].src" target="_blank" class="ui-video-player__error-link">
              Download video
            </a>
          }
        </div>
      }
    </div>
  `,
  styleUrl: './video-player.component.scss'
})
export class VideoPlayerComponent implements OnDestroy {
  @ViewChild('videoElement') videoElement!: ElementRef<HTMLVideoElement>;

  @Input() sources: VideoSource[] = [];
  @Input() tracks: VideoTrack[] = [];
  @Input() poster?: string;
  @Input() size: VideoPlayerSize = 'md';
  @Input() variant: VideoPlayerVariant = 'default';
  @Input() disabled = false;
  @Input() autoplay = false;
  @Input() loop = false;
  @Input() muted = false;
  @Input() playsinline = true;
  @Input() preload: 'none' | 'metadata' | 'auto' = 'metadata';
  @Input() showControls = true;
  @Input() showVolumeControl = true;
  @Input() allowFullscreen = true;
  @Input() ariaLabel = 'Video player';
  @Input() videoAriaLabel = 'Video content';

  @Output() play = new EventEmitter<void>();
  @Output() pause = new EventEmitter<void>();
  @Output() ended = new EventEmitter<void>();
  @Output() timeUpdate = new EventEmitter<number>();
  @Output() volumeChange = new EventEmitter<number>();
  @Output() fullscreenChange = new EventEmitter<boolean>();
  @Output() error = new EventEmitter<Event>();

  // Signals for reactive state
  private _isPlaying = signal(false);
  private _currentTime = signal(0);
  private _duration = signal(0);
  private _volume = signal(1);
  private _isMuted = signal(false);
  private _loading = signal(false);
  private _hasError = signal(false);
  private _errorMessage = signal('');
  private _isFullscreen = signal(false);
  private _controlsVisible = signal(true);

  // Public readonly signals
  isPlaying = this._isPlaying.asReadonly();
  currentTime = this._currentTime.asReadonly();
  duration = this._duration.asReadonly();
  volume = this._volume.asReadonly();
  isMuted = this._isMuted.asReadonly();
  loading = this._loading.asReadonly();
  hasError = this._hasError.asReadonly();
  errorMessage = this._errorMessage.asReadonly();
  isFullscreen = this._isFullscreen.asReadonly();
  controlsVisible = this._controlsVisible.asReadonly();

  // Computed values
  progressPercentage = computed(() => {
    const duration = this.duration();
    const currentTime = this.currentTime();
    return duration > 0 ? (currentTime / duration) * 100 : 0;
  });

  private controlsHideTimer?: number;

  getComponentClasses(): string {
    const classes = [
      'ui-video-player',
      `ui-video-player--${this.size}`,
      `ui-video-player--${this.variant}`
    ];
    
    if (this.disabled) {
      classes.push('ui-video-player--disabled');
    }
    
    if (this.loading()) {
      classes.push('ui-video-player--loading');
    }
    
    if (this.isFullscreen()) {
      classes.push('ui-video-player--fullscreen');
    }
    
    return classes.join(' ');
  }

  ngOnDestroy(): void {
    if (this.controlsHideTimer) {
      clearTimeout(this.controlsHideTimer);
    }
  }

  // Video event handlers
  handleLoadStart(): void {
    this._loading.set(true);
    this._hasError.set(false);
  }

  handleLoadedData(): void {
    if (this.videoElement?.nativeElement) {
      this._duration.set(this.videoElement.nativeElement.duration);
    }
  }

  handleCanPlay(): void {
    this._loading.set(false);
  }

  handlePlay(): void {
    this._isPlaying.set(true);
    this.play.emit();
    this.hideControlsAfterDelay();
  }

  handlePause(): void {
    this._isPlaying.set(false);
    this.pause.emit();
    this.showControlsOverlay();
  }

  handleEnded(): void {
    this._isPlaying.set(false);
    this.ended.emit();
    this.showControlsOverlay();
  }

  handleTimeUpdate(): void {
    if (this.videoElement?.nativeElement) {
      const currentTime = this.videoElement.nativeElement.currentTime;
      this._currentTime.set(currentTime);
      this.timeUpdate.emit(currentTime);
    }
  }

  handleVideoVolumeChange(): void {
    if (this.videoElement?.nativeElement) {
      const video = this.videoElement.nativeElement;
      this._volume.set(video.volume);
      this._isMuted.set(video.muted);
      this.volumeChange.emit(video.volume);
    }
  }

  handleError(event: Event): void {
    this._loading.set(false);
    this._hasError.set(true);
    this._errorMessage.set('Failed to load video');
    this.error.emit(event);
  }

  // Control methods
  togglePlayPause(): void {
    if (!this.videoElement?.nativeElement || this.disabled) return;

    if (this.isPlaying()) {
      this.videoElement.nativeElement.pause();
    } else {
      this.videoElement.nativeElement.play();
    }
  }

  handleSeek(event: Event): void {
    if (!this.videoElement?.nativeElement || this.disabled) return;

    const target = event.target as HTMLInputElement;
    const seekTime = parseFloat(target.value);
    this.videoElement.nativeElement.currentTime = seekTime;
  }

  toggleMute(): void {
    if (!this.videoElement?.nativeElement || this.disabled) return;

    this.videoElement.nativeElement.muted = !this.videoElement.nativeElement.muted;
  }

  handleVolumeSliderChange(event: Event): void {
    if (!this.videoElement?.nativeElement || this.disabled) return;

    const target = event.target as HTMLInputElement;
    const newVolume = parseFloat(target.value);
    this.videoElement.nativeElement.volume = newVolume;
  }

  toggleFullscreen(): void {
    if (!this.allowFullscreen || this.disabled) return;

    if (!document.fullscreenElement) {
      this.videoElement?.nativeElement.requestFullscreen().then(() => {
        this._isFullscreen.set(true);
        this.fullscreenChange.emit(true);
      });
    } else {
      document.exitFullscreen().then(() => {
        this._isFullscreen.set(false);
        this.fullscreenChange.emit(false);
      });
    }
  }

  // Control visibility
  private showControlsOverlay(): void {
    this._controlsVisible.set(true);
    if (this.controlsHideTimer) {
      clearTimeout(this.controlsHideTimer);
    }
  }

  private hideControlsAfterDelay(): void {
    if (this.controlsHideTimer) {
      clearTimeout(this.controlsHideTimer);
    }
    
    this.controlsHideTimer = window.setTimeout(() => {
      if (this.isPlaying()) {
        this._controlsVisible.set(false);
      }
    }, 3000);
  }

  // Utility methods
  formatTime(seconds: number): string {
    if (isNaN(seconds)) return '0:00';
    
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = Math.floor(seconds % 60);
    
    if (hours > 0) {
      return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
    }
    
    return `${minutes}:${secs.toString().padStart(2, '0')}`;
  }
}