import { Injectable } from '@angular/core';

export interface HighlightOptions {
  language: string;
  lineNumbers?: boolean;
  highlightLines?: (number | string)[];
}

@Injectable({
  providedIn: 'root'
})
export class SyntaxHighlighterService {

  private supportedLanguages = new Set([
    'javascript', 'typescript', 'css', 'scss', 'html', 'json', 
    'bash', 'python', 'java', 'csharp', 'markup'
  ]);

  private prismLoaded = false;
  private loadPromise: Promise<any> | null = null;

  constructor() {}

  async highlight(code: string, options: HighlightOptions): Promise<string> {
    const { language } = options;
    
    if (!this.isLanguageSupported(language)) {
      return this.escapeHtml(code);
    }

    try {
      const Prism = await this.loadPrism();
      await this.loadLanguage(language);
      
      const grammar = Prism.languages[language];
      if (!grammar) {
        return this.escapeHtml(code);
      }

      return Prism.highlight(code, grammar, language);
    } catch (error) {
      console.warn('Failed to highlight code:', error);
      return this.escapeHtml(code);
    }
  }

  private async loadPrism(): Promise<any> {
    if (this.prismLoaded && (window as any).Prism) {
      return (window as any).Prism;
    }

    if (this.loadPromise) {
      return this.loadPromise;
    }

    this.loadPromise = new Promise(async (resolve, reject) => {
      try {
        if (typeof window === 'undefined') {
          // Server-side rendering fallback
          resolve({ highlight: () => '', languages: {} });
          return;
        }

        // Load Prism core
        const prismModule = await import('prismjs');
        const Prism = prismModule.default || prismModule;
        
        // Ensure global availability
        (window as any).Prism = Prism;
        
        this.prismLoaded = true;
        resolve(Prism);
      } catch (error) {
        console.warn('Failed to load Prism:', error);
        reject(error);
      }
    });

    return this.loadPromise;
  }

  private async loadLanguage(language: string): Promise<void> {
    if (typeof window === 'undefined') return;
    
    const Prism = (window as any).Prism;
    if (!Prism) return;

    // Check if language is already loaded
    if (Prism.languages[language]) {
      return;
    }

    // Skip loading for unsupported languages or use fallback
    if (!this.isLanguageSupported(language)) {
      return;
    }

    // For now, just use the built-in languages or fallback gracefully
    // This avoids the import issues while still providing basic highlighting
    console.warn(`Language '${language}' not preloaded, using fallback`);
  }

  isLanguageSupported(language: string): boolean {
    return this.supportedLanguages.has(language.toLowerCase());
  }

  detectLanguage(code: string): string {
    // Simple heuristics for language detection
    const trimmedCode = code.trim();
    
    if (trimmedCode.startsWith('<?') || trimmedCode.includes('<html>') || 
        /<\/?[a-z][\s\S]*>/i.test(trimmedCode)) {
      return 'markup';
    }
    
    if (trimmedCode.startsWith('{') || trimmedCode.startsWith('[')) {
      try {
        JSON.parse(trimmedCode);
        return 'json';
      } catch {}
    }
    
    if (trimmedCode.includes('function ') || trimmedCode.includes('const ') || 
        trimmedCode.includes('let ') || trimmedCode.includes('var ')) {
      if (trimmedCode.includes(': ') && (trimmedCode.includes('interface ') || 
          trimmedCode.includes('type '))) {
        return 'typescript';
      }
      return 'javascript';
    }
    
    if (trimmedCode.includes('#') && trimmedCode.includes('def ')) {
      return 'python';
    }
    
    if (trimmedCode.includes('public class ') || trimmedCode.includes('import java.')) {
      return 'java';
    }
    
    if (trimmedCode.includes('using System') || trimmedCode.includes('namespace ')) {
      return 'csharp';
    }
    
    if (trimmedCode.includes('#!/bin/') || trimmedCode.includes('echo ')) {
      return 'bash';
    }
    
    if (trimmedCode.includes('{') && (trimmedCode.includes('color:') || 
        trimmedCode.includes('margin:') || trimmedCode.includes('@'))) {
      return trimmedCode.includes('$') ? 'scss' : 'css';
    }
    
    return 'text';
  }

  getSupportedLanguages(): string[] {
    return Array.from(this.supportedLanguages).sort();
  }

  private escapeHtml(text: string): string {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }
}