import { Component, Input, Output, EventEmitter, forwardRef, TemplateRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export interface SelectOption {
  value: string;
  label: string;
  disabled?: boolean;
}

@Component({
  selector: 'ccl-select',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './select.html',
  styleUrls: ['./select.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => SelectComponent),
      multi: true
    }
  ]
})
export class SelectComponent implements ControlValueAccessor {
  @Input() options: SelectOption[] = [];
  @Input() placeholder = '';
  @Input() disabled = false;
  @Input() readonly = false;
  @Input() error = false;
  @Input() errorMessage = '';
  @Input() helperText = '';
  @Input() multiple = false;
  @Input() size?: number;
  @Input() filterIcon?: TemplateRef<unknown>;
  
  // Prefix icon (left side) configuration
  @Input() showPrefixIcon = false;
  @Input() prefixIcon?: TemplateRef<unknown>;
  @Input() iconBackground: 'none' | 'rounded' | 'square' = 'none';

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

  id = 'ccl-select-' + Math.random().toString(36).substring(2, 9);
  selectedValue: string | string[] = '';

  // ControlValueAccessor implementation
  private onChange = (value: string | string[]) => {};
  private onTouched = () => {};

  writeValue(value: string | string[]): void {
    if (this.multiple) {
      this.selectedValue = Array.isArray(value) ? value : [];
    } else {
      this.selectedValue = value || '';
    }
  }

  registerOnChange(fn: (value: string | string[]) => void): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

  onSelectionChange(event: Event): void {
    const target = event.target as HTMLSelectElement;
    if (this.multiple) {
      const selectedValues = Array.from(target.selectedOptions).map(option => option.value);
      this.selectedValue = selectedValues;
      this.onChange(selectedValues);
      this.selectionChange.emit(selectedValues);
    } else {
      this.selectedValue = target.value;
      this.onChange(target.value);
      this.selectionChange.emit(target.value);
    }
    this.onTouched();
  }

  isSelected(value: string): boolean {
    if (this.multiple) {
      return Array.isArray(this.selectedValue) && this.selectedValue.includes(value);
    }
    // If selectedValue is empty string, only select the placeholder option (value="")
    if (this.selectedValue === '') {
      return value === '';
    }
    return this.selectedValue === value;
  }

  clearSelection(): void {
    if (this.multiple) {
      this.selectedValue = [];
    } else {
      this.selectedValue = '';
    }
    this.onChange(this.selectedValue);
    this.selectionChange.emit(this.selectedValue);
  }

  onContainerClick(event: Event): void {
    // If click is on the select element, do nothing special
    if (event.target instanceof HTMLSelectElement) {
      return;
    }
  
    const selectElement = this.getSelectElement();
    if (!selectElement || this.disabled) return;
  
    event.preventDefault();
    event.stopPropagation();
  
    // Focus the select first
    selectElement.focus({ preventScroll: true });
  
    // Open dropdown using a user-like event sequence
    this.simulateUserClick(selectElement);
  }
  
  /**
   * Simulate user click sequence (mousedown → mouseup → click)
   * Works for most browsers that block programmatic open()
   */
  private simulateUserClick(selectElement: HTMLSelectElement): void {
    // Ensure blur handlers don't interfere
    requestAnimationFrame(() => {
      const rect = selectElement.getBoundingClientRect();
      const centerX = rect.left + rect.width / 2;
      const centerY = rect.top + rect.height / 2;
  
      const events: MouseEvent[] = [
        new MouseEvent('mousedown', {
          bubbles: true,
          cancelable: true,
          clientX: centerX,
          clientY: centerY,
          view: window
        }),
        new MouseEvent('mouseup', {
          bubbles: true,
          cancelable: true,
          clientX: centerX,
          clientY: centerY,
          view: window
        }),
        new MouseEvent('click', {
          bubbles: true,
          cancelable: true,
          clientX: centerX,
          clientY: centerY,
          view: window
        })
      ];
  
      for (const e of events) {
        selectElement.dispatchEvent(e);
      }
    });
  }
  

  private getSelectElement(): HTMLSelectElement | null {
    return document.getElementById(this.id) as HTMLSelectElement;
  }
}
