import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEncapsulation, signal, computed, OnInit, OnDestroy, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ContainerComponent } from 'ui-essentials';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
import { faArrowUp, faUsers, faDollarSign, faChartBar } from '@fortawesome/free-solid-svg-icons';
import { StatisticsConfig, StatisticItem } from '../../interfaces/social-proof.interfaces';

@Component({
  selector: 'ui-lp-statistics-display',
  standalone: true,
  imports: [CommonModule, ContainerComponent, FaIconComponent],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  template: `
    <section 
      class="ui-lp-statistics-display"
      [class]="getComponentClasses()"
      [attr.aria-label]="'Statistics section'"
      #sectionElement>
      
      <ui-container [size]="'xl'" [padding]="'lg'">
        @if (config().title || config().subtitle) {
          <div class="ui-lp-statistics-display__header">
            @if (config().title) {
              <h2 class="ui-lp-statistics-display__title">{{ config().title }}</h2>
            }
            @if (config().subtitle) {
              <p class="ui-lp-statistics-display__subtitle">{{ config().subtitle }}</p>
            }
          </div>
        }
        
        <div 
          class="ui-lp-statistics-display__items"
          [class.ui-lp-statistics-display__items--row]="config().layout === 'row'"
          [class.ui-lp-statistics-display__items--grid]="config().layout === 'grid'">
          
          @for (statistic of config().statistics; track statistic.id; let index = $index) {
            <div 
              class="ui-lp-statistics-display__item"
              [attr.data-animation-delay]="index * 100">
              
              @if (statistic.icon) {
                <div class="ui-lp-statistics-display__icon">
                  <fa-icon [icon]="getIconDefinition(statistic.icon)"></fa-icon>
                </div>
              }
              
              <div class="ui-lp-statistics-display__content">
                <div class="ui-lp-statistics-display__value">
                  @if (statistic.prefix) {
                    <span class="ui-lp-statistics-display__prefix">{{ statistic.prefix }}</span>
                  }
                  
                  <span 
                    class="ui-lp-statistics-display__number"
                    [attr.data-target]="statistic.animateValue ? getNumericValue(statistic.value) : null"
                    [attr.data-animate]="statistic.animateValue">
                    {{ displayValue(statistic) }}
                  </span>
                  
                  @if (statistic.suffix) {
                    <span class="ui-lp-statistics-display__suffix">{{ statistic.suffix }}</span>
                  }
                </div>
                
                <div class="ui-lp-statistics-display__label">{{ statistic.label }}</div>
                
                @if (statistic.description) {
                  <div class="ui-lp-statistics-display__description">{{ statistic.description }}</div>
                }
              </div>
            </div>
          }
        </div>
      </ui-container>
    </section>
  `,
  styleUrl: './statistics-display.component.scss'
})
export class StatisticsDisplayComponent implements OnInit, AfterViewInit, OnDestroy {
  @ViewChild('sectionElement') sectionElement!: ElementRef<HTMLElement>;
  
  config = signal<StatisticsConfig>({
    statistics: [],
    layout: 'row',
    variant: 'minimal',
    animateOnScroll: true,
    backgroundColor: 'transparent'
  });
  
  private intersectionObserver?: IntersectionObserver;
  private animatedItems = new Set<string>();
  
  @Input() set configuration(value: StatisticsConfig) {
    this.config.set(value);
  }
  
  @Output() statisticClicked = new EventEmitter<StatisticItem>();
  
  getComponentClasses(): string {
    const classes = ['ui-lp-statistics-display'];
    
    if (this.config().layout) {
      classes.push(`ui-lp-statistics-display--${this.config().layout}`);
    }
    if (this.config().variant) {
      classes.push(`ui-lp-statistics-display--${this.config().variant}`);
    }
    if (this.config().backgroundColor) {
      classes.push(`ui-lp-statistics-display--${this.config().backgroundColor}`);
    }
    
    return classes.join(' ');
  }
  
  ngOnInit(): void {
    if (this.config().animateOnScroll && 'IntersectionObserver' in window) {
      this.setupIntersectionObserver();
    }
  }
  
  ngAfterViewInit(): void {
    if (!this.config().animateOnScroll) {
      this.animateAllCounters();
    }
  }
  
  ngOnDestroy(): void {
    if (this.intersectionObserver) {
      this.intersectionObserver.disconnect();
    }
  }
  
  displayValue(statistic: StatisticItem): string {
    if (typeof statistic.value === 'number' && !statistic.animateValue) {
      return this.formatNumber(statistic.value);
    }
    return statistic.value.toString();
  }
  
  getNumericValue(value: number | string): number {
    return typeof value === 'number' ? value : parseInt(value.toString(), 10) || 0;
  }
  
  getIconDefinition(iconName: string): IconDefinition {
    const iconMap: { [key: string]: IconDefinition } = {
      'arrow-up': faArrowUp,
      'users': faUsers,
      'dollar-sign': faDollarSign,
      'chart-bar': faChartBar
    };
    return iconMap[iconName] || faChartBar;
  }
  
  private setupIntersectionObserver(): void {
    this.intersectionObserver = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            this.animateCountersInView();
          }
        });
      },
      { threshold: 0.5 }
    );
  }
  
  private animateCountersInView(): void {
    if (!this.sectionElement) return;
    
    const numberElements = this.sectionElement.nativeElement.querySelectorAll(
      '[data-animate="true"]:not(.animated)'
    );
    
    numberElements.forEach((element) => {
      const target = parseInt(element.getAttribute('data-target') || '0', 10);
      const statId = element.closest('.ui-lp-statistics-display__item')?.getAttribute('data-id');
      
      if (statId && !this.animatedItems.has(statId)) {
        this.animatedItems.add(statId);
        element.classList.add('animated');
        this.animateCounter(element as HTMLElement, target);
      }
    });
  }
  
  private animateAllCounters(): void {
    if (!this.sectionElement) return;
    
    const numberElements = this.sectionElement.nativeElement.querySelectorAll('[data-animate="true"]');
    
    numberElements.forEach((element) => {
      const target = parseInt(element.getAttribute('data-target') || '0', 10);
      this.animateCounter(element as HTMLElement, target);
    });
  }
  
  private animateCounter(element: HTMLElement, target: number): void {
    const duration = 2000; // 2 seconds
    const steps = 60;
    const stepValue = target / steps;
    const stepDuration = duration / steps;
    
    let current = 0;
    let step = 0;
    
    const timer = setInterval(() => {
      current = Math.min(target, Math.floor(stepValue * step));
      element.textContent = this.formatNumber(current);
      
      step++;
      
      if (step > steps || current >= target) {
        clearInterval(timer);
        element.textContent = this.formatNumber(target);
      }
    }, stepDuration);
  }
  
  private formatNumber(num: number): string {
    if (num >= 1000000) {
      return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
    }
    if (num >= 1000) {
      return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
    }
    return num.toString();
  }
}