import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { FontTheme, FontDefinition } from '../types/font-types';
import { UiFontManagerService } from '../ui-font-manager.service';

@Injectable({
  providedIn: 'root'
})
export class FontThemeService {
  private themes = new Map<string, FontTheme>();
  private activeThemeSubject = new BehaviorSubject<FontTheme | null>(null);

  constructor(private fontManager: UiFontManagerService) {
    this.initializeDefaultThemes();
  }

  /**
   * Get all available themes
   */
  getThemes(): FontTheme[] {
    return Array.from(this.themes.values());
  }

  /**
   * Get theme by name
   */
  getTheme(name: string): FontTheme | undefined {
    return this.themes.get(name);
  }

  /**
   * Add or update a theme
   */
  addTheme(theme: FontTheme): void {
    this.themes.set(theme.name, theme);
  }

  /**
   * Remove a theme
   */
  removeTheme(name: string): boolean {
    return this.themes.delete(name);
  }

  /**
   * Apply a theme by name
   */
  applyTheme(themeName: string): Observable<boolean> {
    const theme = this.themes.get(themeName);
    if (!theme) {
      console.warn(`Theme "${themeName}" not found`);
      return new BehaviorSubject(false).asObservable();
    }

    return new Observable(observer => {
      this.fontManager.applyTheme(theme).subscribe({
        next: (success) => {
          if (success) {
            this.activeThemeSubject.next(theme);
          }
          observer.next(success);
          observer.complete();
        },
        error: (error) => observer.error(error)
      });
    });
  }

  /**
   * Get currently active theme
   */
  getActiveTheme(): Observable<FontTheme | null> {
    return this.activeThemeSubject.asObservable();
  }

  /**
   * Create theme from font combination
   */
  createThemeFromCombination(name: string, combinationName: string, description?: string): FontTheme | null {
    const theme = this.fontManager.createThemeFromCombination(name, combinationName);
    if (theme && description) {
      theme.description = description;
    }
    if (theme) {
      this.addTheme(theme);
    }
    return theme;
  }

  /**
   * Create custom theme
   */
  createCustomTheme(
    name: string,
    fonts: {
      sans: string;
      serif: string;
      mono: string;
      display: string;
    },
    description?: string
  ): FontTheme | null {
    const allFonts = this.fontManager.getAllFonts();
    
    // Validate all fonts exist
    const fontDefinitions: { [key: string]: FontDefinition } = {};
    for (const [type, fontName] of Object.entries(fonts)) {
      const font = allFonts[fontName];
      if (!font) {
        console.warn(`Font "${fontName}" not found for type "${type}"`);
        return null;
      }
      fontDefinitions[type] = font;
    }

    const theme: FontTheme = {
      name,
      description,
      fonts: {
        sans: fontDefinitions['sans'],
        serif: fontDefinitions['serif'],
        mono: fontDefinitions['mono'],
        display: fontDefinitions['display']
      }
    };

    this.addTheme(theme);
    return theme;
  }

  /**
   * Export theme configuration
   */
  exportTheme(themeName: string): string | null {
    const theme = this.themes.get(themeName);
    if (!theme) return null;
    
    return JSON.stringify(theme, null, 2);
  }

  /**
   * Import theme from configuration
   */
  importTheme(themeJson: string): FontTheme | null {
    try {
      const theme: FontTheme = JSON.parse(themeJson);
      
      // Validate theme structure
      if (!theme.name || !theme.fonts) {
        throw new Error('Invalid theme structure');
      }

      this.addTheme(theme);
      return theme;
    } catch (error) {
      console.error('Failed to import theme:', error);
      return null;
    }
  }

  private initializeDefaultThemes(): void {
    const combinations = this.fontManager.getFontCombinations();
    
    // Create default themes from combinations
    Object.entries(combinations).forEach(([name, combo]) => {
      const theme = this.fontManager.createThemeFromCombination(name, name);
      if (theme) {
        this.addTheme(theme);
      }
    });

    // Add system fonts theme
    const systemTheme: FontTheme = {
      name: 'System',
      description: 'Use system default fonts for optimal performance',
      fonts: {
        sans: {
          family: 'system-ui',
          weights: [400, 500, 600, 700],
          fallbacks: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'],
          loadingStrategy: 'swap',
          category: 'sans-serif'
        },
        serif: {
          family: 'ui-serif',
          weights: [400, 700],
          fallbacks: ['Georgia', 'Cambria', 'Times New Roman', 'Times', 'serif'],
          loadingStrategy: 'swap',
          category: 'serif'
        },
        mono: {
          family: 'ui-monospace',
          weights: [400, 700],
          fallbacks: ['SFMono-Regular', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New', 'monospace'],
          loadingStrategy: 'swap',
          category: 'monospace'
        },
        display: {
          family: 'system-ui',
          weights: [400, 700],
          fallbacks: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'],
          loadingStrategy: 'swap',
          category: 'display'
        }
      }
    };

    this.addTheme(systemTheme);
  }
}