import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, forwardRef, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
import { faSearch, faEnvelope, faTimes, faEye, faEyeSlash, faSpinner } from '@fortawesome/free-solid-svg-icons';

export type TextInputSize = 'sm' | 'md' | 'lg';
export type TextInputVariant = 'outlined' | 'filled' | 'underlined';
export type TextInputType = 'text' | 'email' | 'password' | 'search' | 'number' | 'tel' | 'url';
export type TextInputState = 'default' | 'error' | 'success' | 'warning';

@Component({
  selector: 'ui-text-input',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule, FontAwesomeModule],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => TextInputComponent),
      multi: true
    }
  ],
  template: `
    <div class="text-input-wrapper" [class]="getWrapperClasses()">
      <!-- Label -->
      @if (label) {
        <label 
          class="text-input__label"
          [for]="inputId"
          [class.text-input__label--required]="required"
        >
          {{ label }}
          @if (required) {
            <span class="text-input__required-indicator">*</span>
          }
        </label>
      }
      
      <!-- Input Container -->
      <div class="text-input__container" [class]="getContainerClasses()">
        <!-- Prefix Icon -->
        @if (prefixIcon) {
          <div class="text-input__prefix-icon">
            <fa-icon [icon]="prefixIcon"></fa-icon>
          </div>
        }
        
        <!-- Prefix Text -->
        @if (prefixText) {
          <div class="text-input__prefix-text">{{ prefixText }}</div>
        }
        
        <!-- Input Field -->
        <input
          [id]="inputId"
          class="text-input__field"
          [type]="getInputType()"
          [placeholder]="placeholder"
          [disabled]="disabled"
          [readonly]="readonly"
          [required]="required"
          [min]="min"
          [max]="max"
          [step]="step"
          [attr.maxlength]="maxLength"
          [autocomplete]="autocomplete"
          [value]="value"
          (input)="onInput($event)"
          (focus)="onFocus($event)"
          (blur)="onBlur($event)"
          (keydown)="onKeyDown($event)"
        />
        
        <!-- Suffix Content -->
        <div class="text-input__suffix" [class.text-input__suffix--has-content]="hasSuffixContent()">
          <!-- Clear Button -->
          @if (clearable && value && !disabled) {
            <button
              type="button"
              class="text-input__clear-btn"
              (click)="clearValue()"
              [attr.aria-label]="'Clear ' + (label || 'input')"
            >
              <fa-icon [icon]="faTimes"></fa-icon>
            </button>
          }
          
          <!-- Password Toggle -->
          @if (type === 'password') {
            <button
              type="button"
              class="text-input__password-toggle"
              (click)="togglePasswordVisibility()"
              [attr.aria-label]="passwordVisible() ? 'Hide password' : 'Show password'"
            >
              <fa-icon [icon]="passwordVisible() ? faEyeSlash : faEye"></fa-icon>
            </button>
          }
          
          <!-- Loading Spinner -->
          @if (loading) {
            <div class="text-input__spinner">
              <fa-icon [icon]="faSpinner" [animation]="'spin'"></fa-icon>
            </div>
          }
          
          <!-- Custom Suffix -->
          @if (suffixIcon) {
            <div class="text-input__suffix-icon">
              <fa-icon [icon]="suffixIcon"></fa-icon>
            </div>
          }
        </div>
      </div>
      
      <!-- Helper Text / Error Message -->
      @if (helperText || errorMessage) {
        <div class="text-input__helper-text" [class]="getHelperTextClasses()">
          {{ state === 'error' ? errorMessage : helperText }}
        </div>
      }
      
      <!-- Character Counter -->
      @if (maxLength && showCharacterCount) {
        <div class="text-input__char-counter">
          {{ value.length }}/{{ maxLength }}
        </div>
      }
    </div>
  `,
  styleUrls: ['./text-input.component.scss']
})
export class TextInputComponent implements ControlValueAccessor {
  @Input() label: string = '';
  @Input() placeholder: string = '';
  @Input() type: TextInputType = 'text';
  @Input() size: TextInputSize = 'md';
  @Input() variant: TextInputVariant = 'outlined';
  @Input() state: TextInputState = 'default';
  @Input() disabled = false;
  @Input() readonly = false;
  @Input() required = false;
  @Input() loading = false;
  @Input() clearable = false;
  @Input() prefixIcon: IconDefinition | null = null;
  @Input() prefixText: string = '';
  @Input() suffixIcon: IconDefinition | null = null;
  @Input() helperText: string = '';
  @Input() errorMessage: string = '';
  @Input() maxLength: number | null = null;
  @Input() showCharacterCount = false;
  @Input() autocomplete: string = '';
  @Input() min: string | number | null = null;
  @Input() max: string | number | null = null;
  @Input() step: string | number | null = null;
  @Input() inputId: string = `text-input-${Math.random().toString(36).substr(2, 9)}`;

  @Output() inputChange = new EventEmitter<string>();
  @Output() inputFocus = new EventEmitter<FocusEvent>();
  @Output() inputBlur = new EventEmitter<FocusEvent>();
  @Output() keyDown = new EventEmitter<KeyboardEvent>();
  @Output() clear = new EventEmitter<void>();

  value = '';
  focused = false;
  passwordVisible = signal(false);

  // FontAwesome icons
  readonly faSearch = faSearch;
  readonly faEnvelope = faEnvelope;
  readonly faTimes = faTimes;
  readonly faEye = faEye;
  readonly faEyeSlash = faEyeSlash;
  readonly faSpinner = faSpinner;

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

  writeValue(value: string): void {
    this.value = value || '';
  }

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

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

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

  getWrapperClasses(): string {
    const classes = [
      `text-input-wrapper--${this.size}`,
      `text-input-wrapper--${this.variant}`,
      `text-input-wrapper--${this.state}`
    ];

    if (this.disabled) classes.push('text-input-wrapper--disabled');
    if (this.focused) classes.push('text-input-wrapper--focused');
    if (this.readonly) classes.push('text-input-wrapper--readonly');
    if (this.loading) classes.push('text-input-wrapper--loading');

    return classes.join(' ');
  }

  getContainerClasses(): string {
    const classes: string[] = [];

    if (this.prefixIcon || this.prefixText) classes.push('text-input__container--has-prefix');
    if (this.hasSuffixContent()) classes.push('text-input__container--has-suffix');

    return classes.join(' ');
  }

  getHelperTextClasses(): string {
    const classes = [`text-input__helper-text--${this.state}`];
    return classes.join(' ');
  }

  getInputType(): string {
    if (this.type === 'password') {
      return this.passwordVisible() ? 'text' : 'password';
    }
    return this.type;
  }

  hasSuffixContent(): boolean {
    return !!(
      this.clearable ||
      this.type === 'password' ||
      this.loading ||
      this.suffixIcon
    );
  }

  onInput(event: Event): void {
    const target = event.target as HTMLInputElement;
    this.value = target.value;
    this.onChange(this.value);
    this.inputChange.emit(this.value);
  }

  onFocus(event: FocusEvent): void {
    this.focused = true;
    this.inputFocus.emit(event);
  }

  onBlur(event: FocusEvent): void {
    this.focused = false;
    this.onTouched();
    this.inputBlur.emit(event);
  }

  onKeyDown(event: KeyboardEvent): void {
    this.keyDown.emit(event);
  }

  togglePasswordVisibility(): void {
    this.passwordVisible.set(!this.passwordVisible());
  }

  clearValue(): void {
    this.value = '';
    this.onChange(this.value);
    this.inputChange.emit(this.value);
    this.clear.emit();
  }
}