import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, forwardRef, ViewChild, AfterViewInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
import { TextInputComponent, TextInputSize, TextInputVariant, TextInputType, TextInputState } from './text-input.component';
import { TextareaComponent, TextareaSize, TextareaVariant, TextareaState, TextareaResize } from './textarea.component';

export type InputWrapperMode = 'input' | 'textarea';

@Component({
  selector: 'ui-input-wrapper',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule, TextInputComponent, TextareaComponent],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => InputWrapperComponent),
      multi: true
    }
  ],
  template: `
    @if (mode === 'input') {
      <ui-text-input
        #textInput
        [label]="label"
        [placeholder]="placeholder"
        [type]="inputType"
        [size]="size"
        [variant]="variant"
        [state]="state"
        [disabled]="disabled"
        [readonly]="readonly"
        [required]="required"
        [loading]="loading"
        [clearable]="clearable"
        [prefixIcon]="prefixIcon"
        [prefixText]="prefixText"
        [suffixIcon]="suffixIcon"
        [helperText]="helperText"
        [errorMessage]="errorMessage"
        [maxLength]="maxLength"
        [showCharacterCount]="showCharacterCount"
        [autocomplete]="autocomplete"
        [min]="min"
        [max]="max"
        [step]="step"
        [inputId]="inputId"
        (inputChange)="onInputChange($event)"
        (inputFocus)="onInputFocus($event)"
        (inputBlur)="onInputBlur($event)"
        (keyDown)="onKeyDown($event)"
        (clear)="onClear()"
      />
    }
    
    @if (mode === 'textarea') {
      <ui-textarea
        #textArea
        [label]="label"
        [placeholder]="placeholder"
        [size]="size"
        [variant]="variant"
        [state]="state"
        [disabled]="disabled"
        [readonly]="readonly"
        [required]="required"
        [loading]="loading"
        [clearable]="clearable"
        [prefixIcon]="prefixIcon"
        [suffixIcon]="suffixIcon"
        [helperText]="helperText"
        [errorMessage]="errorMessage"
        [maxLength]="maxLength"
        [showCharacterCount]="showCharacterCount"
        [rows]="rows"
        [cols]="cols"
        [resize]="resize"
        [autoResize]="autoResize"
        [textareaId]="inputId"
        (textareaChange)="onInputChange($event)"
        (textareaFocus)="onInputFocus($event)"
        (textareaBlur)="onInputBlur($event)"
        (keyDown)="onKeyDown($event)"
        (clear)="onClear()"
      />
    }
  `,
  styles: [`
    :host {
      display: block;
      width: 100%;
    }
  `]
})
export class InputWrapperComponent implements ControlValueAccessor, AfterViewInit {
  @ViewChild('textInput') textInput?: TextInputComponent;
  @ViewChild('textArea') textArea?: TextareaComponent;
  @Input() mode: InputWrapperMode = 'input';
  @Input() label: string = '';
  @Input() placeholder: string = '';
  @Input() inputType: TextInputType = 'text';
  @Input() size: TextInputSize | TextareaSize = 'md';
  @Input() variant: TextInputVariant | TextareaVariant = 'outlined';
  @Input() state: TextInputState | TextareaState = '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 = `input-wrapper-${Math.random().toString(36).substr(2, 9)}`;
  
  // Textarea-specific inputs
  @Input() rows: number = 4;
  @Input() cols: number | null = null;
  @Input() resize: TextareaResize = 'vertical';
  @Input() autoResize = false;

  @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 = '';

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

  ngAfterViewInit(): void {
    // Set up the initial value and event forwarding for child components
    this.updateChildComponent();
  }

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

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

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

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

  private updateChildComponent(): void {
    const activeComponent = this.mode === 'input' ? this.textInput : this.textArea;
    if (activeComponent) {
      activeComponent.writeValue(this.value);
      activeComponent.registerOnChange(this.onChange);
      activeComponent.registerOnTouched(this.onTouched);
      activeComponent.setDisabledState(this.disabled);
    }
  }

  onInputChange(value: string): void {
    this.value = value;
    this.onChange(value);
    this.inputChange.emit(value);
  }

  onInputFocus(event: FocusEvent): void {
    this.inputFocus.emit(event);
  }

  onInputBlur(event: FocusEvent): void {
    this.onTouched();
    this.inputBlur.emit(event);
  }

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

  onClear(): void {
    this.clear.emit();
  }
}