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

export interface DropdownOption {
  value: any;
  label: string;
  disabled?: boolean;
  selected?: boolean;
}

@Component({
  selector: 'ccl-dropdown',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './dropdown.html',
  styleUrls: ['./dropdown.css'],
})
export class DropdownComponent implements AfterViewInit, OnDestroy {
  private static currentlyOpenDropdown: DropdownComponent | null = null;
  @Input() options: DropdownOption[] = [];
  @Input() placeholder = 'Select an option';
  @Input() searchable = true;
  @Input() multiple = false;
  @Input() disabled = false;
  @Input() showCheckboxes = true;
  @Input() maxHeight = '200px';
  @Input() width = '100%';
  @Input() customTemplate?: TemplateRef<unknown>;
  @Input() filterIcon = true;
  @Input() searchPlaceholder = 'Search';
  @Input() customClass = '';
  @Input() filterIconContent = '🔍';
  @Input() searchIconContent = '🔍';
  @Input() arrowIconContent = '▼';
  @Input() filterIconTemplate?: TemplateRef<unknown>;
  @Input() searchIconTemplate?: TemplateRef<unknown>;
  @Input() arrowIconTemplate?: TemplateRef<unknown>;

  @Output() selectionChange = new EventEmitter<any | any[]>();
  @Output() searchChange = new EventEmitter<string>();

  @ViewChild('dropdownTrigger', { static: false }) dropdownTrigger!: ElementRef;
  @ViewChild('dropdownMenu', { static: false }) dropdownMenu!: ElementRef;
  @ViewChild('dropdownContainer', { static: false }) dropdownContainer!: ElementRef;

  isOpen = false;
  searchTerm = '';
  filteredOptions: DropdownOption[] = [];
  private documentCaptureListener?: (event: Event) => void;
  
  // Track if we're currently toggling to prevent immediate close
  private isToggling = false;

  ngOnInit() {
    this.filteredOptions = [...this.options];
  }

  ngAfterViewInit(): void {
    this.registerDocumentCaptureListener();
  }

  ngOnDestroy(): void {
    this.removeDocumentCaptureListener();
  }

  

  ngOnChanges() {
    this.filteredOptions = [...this.options];
    this.filterOptions();
  }

  toggleDropdown(event?: Event) {
    if (this.disabled) return;
    
    // Stop propagation to prevent document click handler from firing immediately
    if (event) {
      event.stopPropagation();
    }
    
    this.isToggling = true;
    const wasOpen = this.isOpen;
    this.isOpen = !this.isOpen;
    
    if (this.isOpen) {
      this.registerAsOpen();
      this.focusSearch();
      // Reset toggling flag after a short delay to allow DOM to update
      setTimeout(() => {
        this.isToggling = false;
      }, 0);
    } else {
      this.isToggling = false;
    }
  }

  closeDropdown() {
    this.unregisterAsOpen();
    this.isOpen = false;
    this.searchTerm = '';
    this.filteredOptions = [...this.options];
  }

  onSearchChange() {
    this.filterOptions();
    this.searchChange.emit(this.searchTerm);
  }

  private filterOptions() {
    if (!this.searchTerm.trim()) {
      this.filteredOptions = [...this.options];
    } else {
      this.filteredOptions = this.options.filter(option =>
        option.label.toLowerCase().includes(this.searchTerm.toLowerCase())
      );
    }
  }

  selectOption(option: DropdownOption) {
    if (option.disabled) return;

    if (this.multiple) {
      option.selected = !option.selected;
      const selectedValues = this.options.filter(opt => opt.selected).map(opt => opt.value);
      this.selectionChange.emit(selectedValues);
    } else {
      // Single select
      this.options.forEach(opt => opt.selected = false);
      option.selected = true;
      this.selectionChange.emit(option.value);
      this.closeDropdown();
    }
  }

  getDisplayText(): string {
    if (this.multiple) {
      const selected = this.options.filter(opt => opt.selected);
      if (selected.length === 0) return this.placeholder;
      if (selected.length === 1) return selected[0].label;
      return `${selected.length} selected`;
    } else {
      const selected = this.options.find(opt => opt.selected);
      return selected ? selected.label : this.placeholder;
    }
  }

  getSelectedCount(): number {
    return this.options.filter(opt => opt.selected).length;
  }

  private focusSearch() {
    setTimeout(() => {
      const searchInput = this.dropdownMenu?.nativeElement?.querySelector('input');
      if (searchInput) {
        searchInput.focus();
      }
    }, 0);
  }

  private registerAsOpen() {
    if (
      DropdownComponent.currentlyOpenDropdown &&
      DropdownComponent.currentlyOpenDropdown !== this
    ) {
      DropdownComponent.currentlyOpenDropdown.closeDropdown();
    }
    DropdownComponent.currentlyOpenDropdown = this;
  }

  private unregisterAsOpen() {
    if (DropdownComponent.currentlyOpenDropdown === this) {
      DropdownComponent.currentlyOpenDropdown = null;
    }
  }

  private registerDocumentCaptureListener() {
    if (typeof document === 'undefined' || this.documentCaptureListener) {
      return;
    }

    this.documentCaptureListener = (event: Event) => {
      this.handleDocumentInteraction(event, true);
    };

    document.addEventListener('click', this.documentCaptureListener, true);
  }

  private removeDocumentCaptureListener() {
    if (typeof document === 'undefined' || !this.documentCaptureListener) {
      return;
    }

    document.removeEventListener('click', this.documentCaptureListener, true);
    this.documentCaptureListener = undefined;
  }

  @HostListener('document:click', ['$event'])
  onDocumentClick(event: Event) {
    this.handleDocumentInteraction(event);
  }

  private handleDocumentInteraction(event: Event, fromCapture = false) {
    
    // Skip if we're currently toggling (prevents race condition)
    if (this.isToggling) {
      return;
    }

    // Only close if dropdown is open
    if (!this.isOpen) {
      return;
    }

    const target = event.target as Node;
    
    // Get all possible elements that could contain the click
    const containerElement = this.dropdownContainer?.nativeElement;
    const triggerElement = this.dropdownTrigger?.nativeElement;
    const menuElement = this.dropdownMenu?.nativeElement;
    
    
    // Check if click is inside any part of the dropdown component
    // Check container first (most reliable), then fallback to trigger/menu
    let clickedInside = false;
    
    if (containerElement) {
      clickedInside = containerElement.contains(target);
    } else if (triggerElement || menuElement) {
      // Fallback: check trigger and menu separately if container isn't available
      clickedInside = (triggerElement?.contains(target) || menuElement?.contains(target)) ?? false;
    } else {
      // Last resort: try to find the dropdown element in the DOM
      // This handles cases where ViewChild isn't ready yet
      // Handle text nodes and other node types by checking parent element
      let element: HTMLElement | null = null;
      if (target.nodeType === Node.TEXT_NODE) {
        element = (target as Text).parentElement;
      } else if (target.nodeType === Node.ELEMENT_NODE) {
        element = target as HTMLElement;
      } else {
        // For other node types, try to get parent element
        element = (target as any).parentElement;
      }
      
      const hostElement = element?.closest?.('ccl-dropdown');
      clickedInside = !!hostElement;
      
    }
    
    if (!clickedInside) {
      this.closeDropdown();
    }
  }
}
