import { Component, Input, computed, signal, ChangeDetectionStrategy, ViewEncapsulation, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SyntaxHighlighterService } from '../../services/syntax-highlighter.service';
import { CodeThemeService, CodeTheme } from '../../services/theme.service';
import { CopyButtonDirective } from '../../directives/copy-button.directive';

export type CodeBlockVariant = 'default' | 'minimal' | 'bordered';

@Component({
  selector: 'ui-code-block',
  standalone: true,
  imports: [CommonModule, CopyButtonDirective],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  template: `
    <div [class]="containerClasses()">
      @if (copyable) {
        <button 
          type="button"
          class="code-block__copy-btn"
          [uiCopyButton]="code"
          [attr.aria-label]="'Copy code to clipboard'"
          title="Copy code">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
            <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
          </svg>
        </button>
      }
      
      <pre [class]="preClasses()">
        @if (showLineNumbers && lineCount() > 1) {
          <div class="code-block__line-numbers" [attr.aria-hidden]="true">
            @for (lineNum of lineNumbers(); track lineNum) {
              <div 
                class="code-block__line-number"
                [class.code-block__line-number--highlighted]="isLineHighlighted(lineNum)">
                {{ lineNum }}
              </div>
            }
          </div>
        }
        
        <code 
          [class]="codeClasses()"
          [innerHTML]="highlightedCode()">
        </code>
      </pre>
    </div>
  `,
  styleUrl: './code-block.component.scss'
})
export class CodeBlockComponent implements OnInit, OnChanges {
  @Input() code = '';
  @Input() language = '';
  @Input() theme: CodeTheme | null = null;
  @Input() variant: CodeBlockVariant = 'default';
  @Input() showLineNumbers = true;
  @Input() copyable = true;
  @Input() highlightLines: (number | string)[] = [];
  @Input() startLineNumber = 1;
  @Input() wrap = false;

  constructor(
    private syntaxHighlighter: SyntaxHighlighterService,
    private themeService: CodeThemeService
  ) {}

  readonly finalLanguage = computed(() => {
    if (this.language) {
      return this.language;
    }
    return this.syntaxHighlighter.detectLanguage(this.code);
  });

  readonly highlightedCode = signal('');

  private async updateHighlightedCode() {
    if (!this.code) {
      this.highlightedCode.set('');
      return;
    }
    
    const lang = this.finalLanguage();
    try {
      const highlighted = await this.syntaxHighlighter.highlight(this.code, {
        language: lang,
        lineNumbers: this.showLineNumbers,
        highlightLines: this.highlightLines
      });
      this.highlightedCode.set(highlighted);
    } catch (error) {
      console.warn('Failed to highlight code:', error);
      this.highlightedCode.set(this.escapeHtml(this.code));
    }
  }

  readonly lineCount = computed(() => {
    if (!this.code) return 0;
    
    const lines = this.code.split('\n');
    // Remove the last empty line if the code ends with a newline
    if (lines.length > 1 && lines[lines.length - 1] === '') {
      return lines.length - 1;
    }
    return lines.length;
  });

  readonly lineNumbers = computed(() => {
    const count = this.lineCount();
    return Array.from({ length: count }, (_, i) => i + this.startLineNumber);
  });

  readonly currentTheme = computed(() => {
    return this.theme || this.themeService.theme();
  });

  readonly containerClasses = computed(() => {
    const classes = ['code-block'];
    classes.push(`code-block--${this.variant}`);
    classes.push(`code-theme-${this.currentTheme()}`);
    
    if (this.wrap) classes.push('code-block--wrap');
    if (this.copyable) classes.push('code-block--copyable');
    
    return classes.join(' ');
  });

  readonly preClasses = computed(() => {
    const classes = ['code-block__pre'];
    if (this.showLineNumbers && this.lineCount() > 1) {
      classes.push('code-block__pre--with-line-numbers');
    }
    return classes.join(' ');
  });

  readonly codeClasses = computed(() => {
    const classes = ['code-block__code'];
    classes.push(`language-${this.finalLanguage()}`);
    return classes.join(' ');
  });

  isLineHighlighted(lineNumber: number): boolean {
    return this.highlightLines.some(highlight => {
      if (typeof highlight === 'number') {
        return highlight === lineNumber;
      }
      
      // Handle range format like "5-10"
      const range = highlight.toString().split('-');
      if (range.length === 2) {
        const start = parseInt(range[0], 10);
        const end = parseInt(range[1], 10);
        return lineNumber >= start && lineNumber <= end;
      }
      
      return false;
    });
  }

  ngOnInit(): void {
    this.updateHighlightedCode();
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes['code'] || changes['language']) {
      this.updateHighlightedCode();
    }
  }

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