import { Component, Input, OnInit, OnDestroy, Output, EventEmitter } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Observable, Subject, takeUntil } from 'rxjs';
import { UiFontManagerService } from './ui-font-manager.service';
import { FontThemeService } from './services/font-theme.service';
import { FontLoadingStateService, GlobalLoadingState } from './services/font-loading-state.service';
import { FontTransitionService } from './services/font-transition.service';
import { FontTheme, FontDefinition } from './types/font-types';

@Component({
  selector: 'lib-ui-font-manager',
  standalone: true,
  imports: [CommonModule],
  template: `
    <div class="font-manager" [class.loading]="(loadingState$ | async)?.isLoading">
      
      <!-- Font Theme Selector -->
      <div class="theme-selector" *ngIf="showThemeSelector">
        <label for="theme-select">Font Theme:</label>
        <select 
          id="theme-select" 
          [value]="selectedTheme" 
          (change)="onThemeChange($event)"
          [disabled]="(loadingState$ | async)?.isLoading">
          <option value="">Select a theme...</option>
          <option *ngFor="let theme of availableThemes" [value]="theme.name">
            {{theme.name}} - {{theme.description}}
          </option>
        </select>
      </div>

      <!-- Loading Progress -->
      <div class="loading-progress" *ngIf="(loadingState$ | async)?.isLoading">
        <div class="progress-bar">
          <div 
            class="progress-fill" 
            [style.width.%]="(loadingState$ | async)?.progress || 0">
          </div>
        </div>
        <div class="loading-info">
          Loading fonts: {{(loadingState$ | async)?.loadedFonts}}/{{(loadingState$ | async)?.totalFonts}}
          <span *ngIf="(loadingState$ | async)?.currentlyLoading?.length">
            ({{(loadingState$ | async)?.currentlyLoading?.join(', ')}})
          </span>
        </div>
      </div>

      <!-- Error Display -->
      <div class="error-messages" *ngIf="hasErrors">
        <div *ngFor="let error of errorMessages" class="error-message">
          <strong>{{error.fontName}}:</strong> {{error.message}}
        </div>
      </div>

      <!-- Font Preview -->
      <div class="font-preview" *ngIf="showPreview">
        <div class="preview-text sans" style="font-family: var(--font-family-sans, inherit)">
          Sans-serif: The quick brown fox jumps over the lazy dog
        </div>
        <div class="preview-text serif" style="font-family: var(--font-family-serif, inherit)">
          Serif: The quick brown fox jumps over the lazy dog
        </div>
        <div class="preview-text mono" style="font-family: var(--font-family-mono, inherit)">
          Mono: The quick brown fox jumps over the lazy dog
        </div>
        <div class="preview-text display" style="font-family: var(--font-family-display, inherit)">
          Display: The quick brown fox jumps over the lazy dog
        </div>
      </div>

    </div>
  `,
  styles: `
    .font-manager {
      padding: 1rem;
      border: 1px solid #e0e0e0;
      border-radius: 8px;
      background: #fafafa;
      max-width: 600px;
    }

    .font-manager.loading {
      opacity: 0.8;
      pointer-events: none;
    }

    .theme-selector {
      margin-bottom: 1rem;
    }

    .theme-selector label {
      display: block;
      margin-bottom: 0.5rem;
      font-weight: 600;
      color: #333;
    }

    .theme-selector select {
      width: 100%;
      padding: 0.5rem;
      border: 1px solid #ccc;
      border-radius: 4px;
      font-size: 0.9rem;
    }

    .loading-progress {
      margin-bottom: 1rem;
    }

    .progress-bar {
      width: 100%;
      height: 8px;
      background: #e0e0e0;
      border-radius: 4px;
      overflow: hidden;
      margin-bottom: 0.5rem;
    }

    .progress-fill {
      height: 100%;
      background: linear-gradient(90deg, #4CAF50, #2196F3);
      transition: width 0.3s ease;
    }

    .loading-info {
      font-size: 0.8rem;
      color: #666;
    }

    .error-messages {
      margin-bottom: 1rem;
    }

    .error-message {
      padding: 0.5rem;
      background: #ffebee;
      border: 1px solid #f44336;
      border-radius: 4px;
      margin-bottom: 0.5rem;
      font-size: 0.85rem;
      color: #c62828;
    }

    .font-preview {
      border-top: 1px solid #e0e0e0;
      padding-top: 1rem;
    }

    .preview-text {
      margin-bottom: 0.75rem;
      padding: 0.5rem;
      background: white;
      border-radius: 4px;
      border-left: 4px solid #2196F3;
    }

    .preview-text.sans { border-left-color: #4CAF50; }
    .preview-text.serif { border-left-color: #FF9800; }
    .preview-text.mono { 
      border-left-color: #9C27B0;
      font-size: 0.9em;
    }
    .preview-text.display { 
      border-left-color: #f44336;
      font-size: 1.1em;
      font-weight: 600;
    }
  `
})
export class UiFontManagerComponent implements OnInit, OnDestroy {
  @Input() showThemeSelector: boolean = true;
  @Input() showPreview: boolean = true;
  @Input() showLoadingProgress: boolean = true;
  @Input() previewText: string = 'The quick brown fox jumps over the lazy dog';
  
  @Output() themeChanged = new EventEmitter<string>();
  @Output() fontLoaded = new EventEmitter<string>();
  @Output() fontError = new EventEmitter<{fontName: string, error: string}>();

  availableThemes: FontTheme[] = [];
  selectedTheme: string = '';
  loadingState$: Observable<GlobalLoadingState>;
  hasErrors: boolean = false;
  errorMessages: {fontName: string, message: string}[] = [];

  private destroy$ = new Subject<void>();

  constructor(
    private fontManager: UiFontManagerService,
    private themeService: FontThemeService,
    private loadingStateService: FontLoadingStateService,
    private transitionService: FontTransitionService
  ) {
    this.loadingState$ = this.loadingStateService.getGlobalState();
  }

  ngOnInit(): void {
    // Load available themes
    this.availableThemes = this.themeService.getThemes();

    // Monitor loading state for errors
    this.loadingState$
      .pipe(takeUntil(this.destroy$))
      .subscribe(state => {
        this.hasErrors = Object.keys(state.errors).length > 0;
        this.errorMessages = Object.entries(state.errors).map(([fontName, message]) => ({
          fontName,
          message
        }));
      });

    // Listen for active theme changes
    this.themeService.getActiveTheme()
      .pipe(takeUntil(this.destroy$))
      .subscribe(theme => {
        if (theme) {
          this.selectedTheme = theme.name;
        }
      });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  onThemeChange(event: Event): void {
    const target = event.target as HTMLSelectElement;
    const themeName = target.value;
    
    if (!themeName) return;

    this.selectedTheme = themeName;
    
    // Apply theme with smooth transition
    this.themeService.applyTheme(themeName)
      .pipe(takeUntil(this.destroy$))
      .subscribe({
        next: (success) => {
          if (success) {
            this.themeChanged.emit(themeName);
          }
        },
        error: (error) => {
          console.error('Failed to apply theme:', error);
          this.fontError.emit({fontName: themeName, error: error.message});
        }
      });
  }

  /**
   * Programmatically load a font
   */
  loadFont(fontName: string): void {
    this.fontManager.loadFont(fontName)
      .pipe(takeUntil(this.destroy$))
      .subscribe({
        next: (success) => {
          if (success) {
            this.fontLoaded.emit(fontName);
          }
        },
        error: (error) => {
          this.fontError.emit({fontName, error: error.message});
        }
      });
  }

  /**
   * Apply theme with custom transition
   */
  applyThemeWithTransition(themeName: string, transitionType: 'fade' | 'scale' | 'typewriter' = 'fade'): void {
    const theme = this.themeService.getTheme(themeName);
    if (!theme) return;

    const fontVariables = {
      '--font-family-sans': this.buildFontStack(theme.fonts.sans),
      '--font-family-serif': this.buildFontStack(theme.fonts.serif),
      '--font-family-mono': this.buildFontStack(theme.fonts.mono),
      '--font-family-display': this.buildFontStack(theme.fonts.display)
    };

    let transition$: Observable<void>;
    
    switch (transitionType) {
      case 'scale':
        transition$ = this.transitionService.applyWithScale(fontVariables);
        break;
      case 'typewriter':
        transition$ = this.transitionService.applyTypewriterTransition(fontVariables);
        break;
      default:
        transition$ = this.transitionService.applyWithFade(fontVariables);
    }

    transition$
      .pipe(takeUntil(this.destroy$))
      .subscribe({
        next: () => {
          this.selectedTheme = themeName;
          this.themeChanged.emit(themeName);
        },
        error: (error) => {
          this.fontError.emit({fontName: themeName, error: error.message});
        }
      });
  }

  private buildFontStack(font: FontDefinition): string {
    return [font.family, ...font.fallbacks]
      .map(f => f.includes(' ') ? `"${f}"` : f)
      .join(', ');
  }
}
