import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, forwardRef, signal, ViewChild, ElementRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export type SwitchSize = 'sm' | 'md' | 'lg';
export type SwitchVariant = 'primary' | 'secondary' | 'success' | 'warning' | 'danger';
export type SwitchState = 'default' | 'disabled';

@Component({
  selector: 'ui-switch',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule, FormsModule],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => SwitchComponent),
      multi: true
    }
  ],
  template: `
    <div class="switch-wrapper" [class]="getWrapperClasses()">
      <label class="switch" [class]="getSwitchClasses()" [for]="switchId">
        <input
          #switchInput
          type="checkbox"
          class="switch__input"
          [id]="switchId"
          [checked]="isChecked()"
          [disabled]="disabled"
          [required]="required"
          [attr.aria-label]="ariaLabel || label || 'Switch'"
          [attr.aria-describedby]="helperText ? switchId + '-helper' : null"
          [attr.aria-invalid]="state === 'disabled' ? null : false"
          (change)="onToggle($event)"
          (focus)="onFocus($event)"
          (blur)="onBlur($event)"
          (keydown)="onKeyDown($event)"
        />
        <span class="switch__track" [class]="getTrackClasses()">
          <span class="switch__thumb" [class]="getThumbClasses()"></span>
        </span>
        @if (label) {
          <span class="switch__label" [class]="getLabelClasses()">
            {{ label }}
            @if (required) {
              <span class="switch__required-indicator">*</span>
            }
          </span>
        }
      </label>

      @if (helperText && state !== 'disabled') {
        <div class="switch__helper-text" [id]="switchId + '-helper'">{{ helperText }}</div>
      }
    </div>
  `,
  styleUrls: ['./switch.component.scss']
})
export class SwitchComponent implements ControlValueAccessor {
  @ViewChild('switchInput', { static: true }) switchInput!: ElementRef<HTMLInputElement>;

  // Core inputs
  @Input() label: string = '';
  @Input() size: SwitchSize = 'md';
  @Input() variant: SwitchVariant = 'primary';
  @Input() state: SwitchState = 'default';
  
  // Behavior inputs
  @Input() disabled = false;
  @Input() required = false;
  @Input() autofocus = false;
  
  // Accessibility
  @Input() ariaLabel: string = '';
  @Input() helperText: string = '';
  @Input() switchId: string = `switch-${Math.random().toString(36).substr(2, 9)}`;

  // Outputs
  @Output() switchChange = new EventEmitter<boolean>();
  @Output() switchFocus = new EventEmitter<FocusEvent>();
  @Output() switchBlur = new EventEmitter<FocusEvent>();

  // Internal state
  protected isChecked = signal<boolean>(false);
  protected isFocused = signal<boolean>(false);

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

  ngAfterViewInit(): void {
    if (this.autofocus) {
      this.switchInput.nativeElement.focus();
    }
  }

  writeValue(value: boolean): void {
    this.isChecked.set(!!value);
  }

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

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

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

  // Event handlers
  onToggle(event: Event): void {
    const target = event.target as HTMLInputElement;
    const checked = target.checked;
    
    this.isChecked.set(checked);
    this.onChange(checked);
    this.switchChange.emit(checked);
  }

  onFocus(event: FocusEvent): void {
    this.isFocused.set(true);
    this.switchFocus.emit(event);
  }

  onBlur(event: FocusEvent): void {
    this.isFocused.set(false);
    this.onTouched();
    this.switchBlur.emit(event);
  }

  onKeyDown(event: KeyboardEvent): void {
    // Space or Enter can toggle the switch
    if (event.key === ' ' || event.key === 'Enter') {
      event.preventDefault();
      if (!this.disabled) {
        const newValue = !this.isChecked();
        this.isChecked.set(newValue);
        this.onChange(newValue);
        this.switchChange.emit(newValue);
        
        // Update the actual input element
        this.switchInput.nativeElement.checked = newValue;
      }
    }
  }

  // CSS class getters
  getWrapperClasses(): string {
    const classes = [
      `switch-wrapper--${this.size}`,
      `switch-wrapper--${this.variant}`,
      `switch-wrapper--${this.state}`
    ];

    if (this.disabled) classes.push('switch-wrapper--disabled');
    if (this.isChecked()) classes.push('switch-wrapper--checked');
    if (this.isFocused()) classes.push('switch-wrapper--focused');

    return classes.join(' ');
  }

  getSwitchClasses(): string {
    const classes = [
      `switch--${this.size}`,
      `switch--${this.variant}`,
      `switch--${this.state}`
    ];

    if (this.disabled) classes.push('switch--disabled');
    if (this.isChecked()) classes.push('switch--checked');
    if (this.isFocused()) classes.push('switch--focused');

    return classes.join(' ');
  }

  getTrackClasses(): string {
    const classes = [`switch__track--${this.size}`];
    
    if (this.isChecked()) classes.push('switch__track--checked');
    if (this.disabled) classes.push('switch__track--disabled');
    
    return classes.join(' ');
  }

  getThumbClasses(): string {
    const classes = [`switch__thumb--${this.size}`];
    
    if (this.isChecked()) classes.push('switch__thumb--checked');
    if (this.disabled) classes.push('switch__thumb--disabled');
    
    return classes.join(' ');
  }

  getLabelClasses(): string {
    const classes = [`switch__label--${this.size}`];
    
    if (this.disabled) classes.push('switch__label--disabled');
    
    return classes.join(' ');
  }
}