import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { faCheck, faTimes } from '@fortawesome/free-solid-svg-icons';

export interface StepperStep {
  id: string;
  title: string;
  description?: string;
  completed?: boolean;
  current?: boolean;
  error?: boolean;
  disabled?: boolean;
  optional?: boolean;
}

export type StepperOrientation = 'horizontal' | 'vertical';
export type StepperSize = 'sm' | 'md' | 'lg';
export type StepperVariant = 'default' | 'outlined';

@Component({
  selector: 'ui-stepper',
  standalone: true,
  imports: [CommonModule, FontAwesomeModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  template: `
    <div [class]="getStepperClasses()">
      @for (step of steps; track step.id; let i = $index; let isLast = $last) {
        <div class="ui-stepper__step">
          <div 
            [class]="getStepHeaderClasses(step)"
            [attr.role]="clickable ? 'button' : 'presentation'"
            [attr.tabindex]="getTabIndex(step)"
            [attr.aria-current]="step.current ? 'step' : null"
            [attr.aria-disabled]="step.disabled"
            (click)="onStepClick(step, i)"
            (keydown)="onStepKeydown($event, step, i)">
            
            <div [class]="getStepIndicatorClasses(step)">
              @if (step.completed && !step.error) {
                <fa-icon [icon]="checkIcon" />
              } @else if (step.error) {
                <fa-icon [icon]="errorIcon" />
              } @else {
                {{ i + 1 }}
              }
            </div>
            
            <div class="ui-stepper__step-content">
              <h4 class="ui-stepper__step-title">{{ step.title }}</h4>
              @if (step.description) {
                <p class="ui-stepper__step-description">{{ step.description }}</p>
              }
            </div>
          </div>
          
          @if (!isLast) {
            <div [class]="getConnectorClasses(step, steps[i + 1]) + ' ui-stepper__connector--outgoing'"></div>
          }
          @if (i > 0) {
            <div [class]="getConnectorClasses(steps[i - 1], step) + ' ui-stepper__connector--incoming'"></div>
          }
        </div>
      }
    </div>
  `,
  styleUrl: './stepper.component.scss'
})
export class StepperComponent {
  @Input() steps: StepperStep[] = [];
  @Input() orientation: StepperOrientation = 'horizontal';
  @Input() size: StepperSize = 'md';
  @Input() variant: StepperVariant = 'default';
  @Input() dense = false;
  @Input() clickable = false;
  @Input() linear = true;
  
  @Output() stepClick = new EventEmitter<{step: StepperStep, index: number}>();
  @Output() stepChange = new EventEmitter<{step: StepperStep, index: number}>();
  
  checkIcon = faCheck;
  errorIcon = faTimes;
  
  getStepperClasses(): string {
    return [
      'ui-stepper',
      `ui-stepper--${this.orientation}`,
      `ui-stepper--${this.size}`,
      this.variant === 'outlined' ? 'ui-stepper--outlined' : '',
      this.dense ? 'ui-stepper--dense' : ''
    ].filter(Boolean).join(' ');
  }
  
  getStepHeaderClasses(step: StepperStep): string {
    return [
      'ui-stepper__step-header',
      step.disabled ? 'ui-stepper__step-header--disabled' : ''
    ].filter(Boolean).join(' ');
  }
  
  getStepIndicatorClasses(step: StepperStep): string {
    let state = 'pending';
    
    if (step.disabled) {
      state = 'disabled';
    } else if (step.error) {
      state = 'error';
    } else if (step.completed) {
      state = 'completed';
    } else if (step.current) {
      state = 'current';
    }
    
    return [
      'ui-stepper__step-indicator',
      `ui-stepper__step-indicator--${state}`
    ].filter(Boolean).join(' ');
  }
  
  getConnectorClasses(currentStep: StepperStep, nextStep: StepperStep): string {
    let state = 'default';
    
    if (currentStep.error) {
      state = 'error';
    } else if (currentStep.completed && !nextStep.error) {
      state = 'completed';
    }
    
    return [
      'ui-stepper__connector',
      state !== 'default' ? `ui-stepper__connector--${state}` : ''
    ].filter(Boolean).join(' ');
  }
  
  getTabIndex(step: StepperStep): number {
    if (!this.clickable || step.disabled) {
      return -1;
    }
    
    if (this.linear) {
      // In linear mode, only allow interaction with current step and completed steps
      return step.current || step.completed ? 0 : -1;
    }
    
    return 0;
  }
  
  onStepClick(step: StepperStep, index: number): void {
    if (!this.clickable || step.disabled) {
      return;
    }
    
    if (this.linear && !step.current && !step.completed) {
      // In linear mode, don't allow clicking on future steps
      return;
    }
    
    this.stepClick.emit({ step, index });
    
    if (!step.current) {
      this.updateCurrentStep(index);
      this.stepChange.emit({ step, index });
    }
  }
  
  onStepKeydown(event: KeyboardEvent, step: StepperStep, index: number): void {
    if (event.key === 'Enter' || event.key === ' ') {
      event.preventDefault();
      this.onStepClick(step, index);
    }
    
    // Arrow navigation
    if (this.clickable && ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.key)) {
      event.preventDefault();
      this.handleArrowNavigation(event.key, index);
    }
  }
  
  private handleArrowNavigation(key: string, currentIndex: number): void {
    const isHorizontal = this.orientation === 'horizontal';
    const isForward = (isHorizontal && key === 'ArrowRight') || (!isHorizontal && key === 'ArrowDown');
    const isBackward = (isHorizontal && key === 'ArrowLeft') || (!isHorizontal && key === 'ArrowUp');
    
    if (!isForward && !isBackward) return;
    
    const direction = isForward ? 1 : -1;
    let targetIndex = currentIndex + direction;
    
    // Find next available step
    while (targetIndex >= 0 && targetIndex < this.steps.length) {
      const targetStep = this.steps[targetIndex];
      
      if (!targetStep.disabled && this.getTabIndex(targetStep) >= 0) {
        this.focusStep(targetIndex);
        break;
      }
      
      targetIndex += direction;
    }
  }
  
  private focusStep(index: number): void {
    // This would require ViewChild to focus the element
    // For now, emit an event that parent can handle
    const step = this.steps[index];
    if (step) {
      this.stepClick.emit({ step, index });
    }
  }
  
  private updateCurrentStep(newCurrentIndex: number): void {
    this.steps.forEach((step, index) => {
      step.current = index === newCurrentIndex;
    });
  }
  
  // Public methods for programmatic control
  public goToStep(index: number): void {
    if (index >= 0 && index < this.steps.length) {
      const step = this.steps[index];
      if (!step.disabled && (!this.linear || step.completed || step.current || index === 0)) {
        this.updateCurrentStep(index);
        this.stepChange.emit({ step, index });
      }
    }
  }
  
  public markStepCompleted(index: number, completed = true): void {
    if (index >= 0 && index < this.steps.length) {
      this.steps[index].completed = completed;
      this.steps[index].error = false; // Clear error when marking completed
    }
  }
  
  public markStepError(index: number, error = true): void {
    if (index >= 0 && index < this.steps.length) {
      this.steps[index].error = error;
      if (error) {
        this.steps[index].completed = false; // Clear completed when marking error
      }
    }
  }
  
  public nextStep(): void {
    const currentIndex = this.steps.findIndex(step => step.current);
    if (currentIndex >= 0 && currentIndex < this.steps.length - 1) {
      // Mark current step as completed if not already
      if (!this.steps[currentIndex].completed && !this.steps[currentIndex].error) {
        this.markStepCompleted(currentIndex);
      }
      
      this.goToStep(currentIndex + 1);
    }
  }
  
  public previousStep(): void {
    const currentIndex = this.steps.findIndex(step => step.current);
    if (currentIndex > 0) {
      this.goToStep(currentIndex - 1);
    }
  }
  
  public resetStepper(): void {
    this.steps.forEach((step, index) => {
      step.current = index === 0;
      step.completed = false;
      step.error = false;
    });
  }
}