import {
  ChangeDetectionStrategy,
  Component,
  computed,
  input,
  model,
  output,
  effect,
  OnDestroy,
  inject,
  viewChild,
  ElementRef,
  untracked,
} from '@angular/core';
import { ButtonComponent } from '../button.component';
import { ButtonColor, ButtonSize } from '../types';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { isaActionCheck } from '@isa/icons';
import {
  animate,
  AnimationBuilder,
  style,
  transition,
  trigger,
} from '@angular/animations';

export type StatefulButtonState = 'default' | 'success' | 'error';

@Component({
  selector: 'ui-stateful-button',
  templateUrl: './stateful-button.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [ButtonComponent, NgIcon],
  providers: [provideIcons({ isaActionCheck })],
  animations: [
    trigger('fade', [
      transition(':enter', [
        style({ opacity: 0.5 }),
        animate('125ms 125ms ease-in', style({ opacity: 1 })),
      ]),
      transition(':leave', [
        style({ opacity: '*' }),
        animate('124ms ease-out', style({ opacity: 0.5 })),
      ]),
    ]),
  ],
})
export class StatefulButtonComponent implements OnDestroy {
  #animationBuilder = inject(AnimationBuilder);
  private buttonElement = viewChild.required(ButtonComponent, {
    read: ElementRef,
  });

  // State management
  state = model<StatefulButtonState>('default');

  stateEffect = effect(() => {
    this.state();

    untracked(() => {
      this.#makeWidthAnimation(this.widthStyle());
    });
  });

  // Content inputs for each state
  defaultContent = input.required<string>();
  successContent = input.required<string>();
  errorContent = input.required<string>();
  errorAction = input<string>();

  // Width configuration for each state
  defaultWidth = input<string>('100%');
  successWidth = input<string>('100%');
  errorWidth = input<string>('100%');

  // Optional dismiss timeout in milliseconds
  dismiss = input<number>(5000);

  // Button properties
  color = input<ButtonColor>('primary');
  size = input<ButtonSize>('medium');
  pending = input<boolean>(false);
  disabled = input<boolean>(false);

  // Output events
  clicked = output<void>();
  action = output<void>();

  // Internal state
  private dismissTimer: ReturnType<typeof setTimeout> | null = null;
  // Computed properties
  stateClass = computed(() => `stateful-button--${this.state()}`);

  widthStyle = computed(() => {
    switch (this.state()) {
      case 'success':
        return this.successWidth();
      case 'error':
        return this.errorWidth();
      default:
        return this.defaultWidth();
    }
  });

  constructor() {
    // Watch for state changes to handle auto-dismiss
    this.setupStateEffect();
  }

  ngOnDestroy(): void {
    this.clearDismissTimer();
  }

  private setupStateEffect(): void {
    // Use effect to watch state changes
    effect(() => {
      const currentState = this.state();
      const dismissTimeout = this.dismiss();

      // Clear any existing timer
      this.clearDismissTimer();

      // Set up auto-dismiss if configured
      if (
        dismissTimeout &&
        (currentState === 'success' || currentState === 'error')
      ) {
        this.dismissTimer = setTimeout(() => {
          this.changeState('default');
        }, dismissTimeout);
      }
    });
  }

  handleButtonClick(): void {
    const currentState = this.state();

    if (currentState === 'default') {
      // Only emit click event in default state
      this.clicked.emit();
    } else if (currentState === 'success' || currentState === 'error') {
      // In success/error states, clicking the button returns to default
      this.changeState('default');
    }
  }

  handleActionClick(event: Event): void {
    // Prevent button click from firing
    event.stopPropagation();

    // Emit action event
    this.action.emit();
  }

  private changeState(newState: StatefulButtonState): void {
    this.clearDismissTimer();
    this.state.set(newState);
  }

  private clearDismissTimer(): void {
    if (this.dismissTimer) {
      clearTimeout(this.dismissTimer);
      this.dismissTimer = null;
    }
  }

  #makeWidthAnimation(width: string): void {
    const animation = this.#animationBuilder.build([
      style({ width: '*' }),
      animate('250ms', style({ width })),
    ]);

    const player = animation.create(this.buttonElement().nativeElement);
    player.play();
  }
}
