import { Component, Input, Output, EventEmitter, HostListener, ElementRef, ViewChild, AfterViewInit, OnChanges, TemplateRef } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'ccl-modal',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './modal.html',
  styleUrls: ['./modal.css']
})
export class ModalComponent implements AfterViewInit, OnChanges {
  @Input() isOpen = false;
  @Input() title: string | TemplateRef<unknown> | null = '';
  @Input() size: 'sm' | 'md' | 'lg' = 'md';
  @Input() ariaLabel?: string;
  @Input() hideCloseButton = false;
  @Input() disableCloseButton = false;
  @Output() closed = new EventEmitter<void>();

  @ViewChild('modalContent', { static: false }) modalContent?: ElementRef<HTMLElement>;
  @ViewChild('closeButton', { static: false }) closeButton?: ElementRef<HTMLButtonElement>;

  private previousActiveElement?: HTMLElement;

  ngAfterViewInit() {
    if (this.isOpen) {
      this.setupFocusManagement();
    }
  }

  @HostListener('keydown', ['$event'])
  onKeydown(event: KeyboardEvent): void {
    if (event.key === 'Escape' && this.isOpen) {
      this.close();
    }
  }

  ngOnChanges() {
    if (this.isOpen) {
      this.setupFocusManagement();
    } else {
      this.restoreFocus();
    }
  }

  private setupFocusManagement(): void {
    // Store the previously focused element
    this.previousActiveElement = document.activeElement as HTMLElement;
    
    // Focus the modal content or close button
    setTimeout(() => {
      if (this.closeButton?.nativeElement) {
        this.closeButton.nativeElement.focus();
      } else if (this.modalContent?.nativeElement) {
        this.modalContent.nativeElement.focus();
      }
    }, 0);
  }

  private restoreFocus(): void {
    if (this.previousActiveElement) {
      this.previousActiveElement.focus();
      this.previousActiveElement = undefined;
    }
  }

  close() {
    this.closed.emit();
  }

  onOverlayClick(event: MouseEvent) {
    if (event.target === event.currentTarget) {
      this.close();
    }
  }

  private _modalId: string = `modal-${Math.random().toString(36).substring(2, 9)}`;
  
  get modalId(): string {
    return this._modalId;
  }

  get titleId(): string {
    return `${this.modalId}-title`;
  }

  get ariaAttributes(): { [key: string]: any } {
    const attrs: { [key: string]: any } = {
      'role': 'dialog',
      'aria-modal': 'true'
    };
    
    if (this.hasTitle) {
      attrs['aria-labelledby'] = this.titleId;
    } else if (this.ariaLabel) {
      attrs['aria-label'] = this.ariaLabel;
    }
    
    return attrs;
  }

  get isStringTitle(): boolean {
    return typeof this.title === 'string';
  }

  get stringTitle(): string {
    return this.isStringTitle ? (this.title as string) : '';
  }

  get templateTitle(): TemplateRef<unknown> | null {
    return this.isTemplateRefTitle(this.title) ? this.title : null;
  }

  get hasTitle(): boolean {
    if (this.isStringTitle) {
      return this.stringTitle.trim().length > 0;
    }

    return !!this.templateTitle;
  }

  private isTemplateRefTitle(title: unknown): title is TemplateRef<unknown> {
    return title instanceof TemplateRef;
  }
}