import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEncapsulation, ElementRef, ViewChild, OnInit, OnDestroy, signal } from '@angular/core';
import { CommonModule } from '@angular/common';

type FeedLayoutSize = 'sm' | 'md' | 'lg';

export interface FeedItem {
  id: string;
  [key: string]: any;
}

@Component({
  selector: 'ui-feed-layout',
  standalone: true,
  imports: [CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  template: `
    <div 
      class="ui-feed-layout"
      [class]="getFeedLayoutClasses()"
      [attr.aria-busy]="loading"
      [attr.aria-label]="ariaLabel"
      role="feed">
      
      @if (enableRefresh && isRefreshing()) {
        <div class="ui-feed-layout__refresh-indicator" aria-hidden="true">
          <div class="ui-feed-layout__refresh-spinner"></div>
          <span>Refreshing...</span>
        </div>
      }
      
      <div 
        class="ui-feed-layout__container"
        #scrollContainer
        (scroll)="handleScroll($event)"
        role="log"
        aria-live="polite"
        aria-atomic="false">
        
        <ng-content></ng-content>
        
        @if (loading && !isRefreshing()) {
          <div class="ui-feed-layout__loader" role="status" aria-live="polite">
            <div class="ui-feed-layout__loader-spinner" aria-hidden="true"></div>
            <span class="ui-feed-layout__loader-text">Loading more content...</span>
          </div>
        }
        
        @if (hasError) {
          <div class="ui-feed-layout__error" role="alert">
            <span>{{ errorMessage || 'Failed to load content' }}</span>
            <button 
              type="button" 
              class="ui-feed-layout__retry-button"
              (click)="handleRetry()"
              [disabled]="loading">
              Retry
            </button>
          </div>
        }
        
        @if (isEmpty && !loading) {
          <div class="ui-feed-layout__empty" role="status">
            <ng-content select="[slot=empty]">
              <span>No content available</span>
            </ng-content>
          </div>
        }
      </div>
      
      @if (enableRefresh) {
        <div 
          class="ui-feed-layout__refresh-zone"
          [class.ui-feed-layout__refresh-zone--active]="isPullingToRefresh()"
          (touchstart)="handleTouchStart($event)"
          (touchmove)="handleTouchMove($event)"
          (touchend)="handleTouchEnd($event)">
        </div>
      }
    </div>
  `,
  styleUrl: './feed-layout.component.scss'
})
export class FeedLayoutComponent implements OnInit, OnDestroy {
  @Input() size: FeedLayoutSize = 'md';
  @Input() loading = false;
  @Input() hasError = false;
  @Input() errorMessage = '';
  @Input() isEmpty = false;
  @Input() enableInfiniteScroll = true;
  @Input() enableRefresh = true;
  @Input() scrollThreshold = 200;
  @Input() refreshThreshold = 80;
  @Input() ariaLabel = 'Content feed';
  
  @Output() loadMore = new EventEmitter<void>();
  @Output() refresh = new EventEmitter<void>();
  @Output() retry = new EventEmitter<void>();
  @Output() scrolled = new EventEmitter<Event>();
  
  @ViewChild('scrollContainer', { static: true }) scrollContainer!: ElementRef<HTMLDivElement>;
  
  protected readonly isRefreshing = signal(false);
  protected readonly isPullingToRefresh = signal(false);
  
  private touchStartY = 0;
  private touchCurrentY = 0;
  private scrollThrottleTimer: number | null = null;
  private resizeObserver?: ResizeObserver;
  
  ngOnInit(): void {
    this.setupResizeObserver();
  }
  
  ngOnDestroy(): void {
    if (this.scrollThrottleTimer) {
      clearTimeout(this.scrollThrottleTimer);
    }
    this.resizeObserver?.disconnect();
  }
  
  getFeedLayoutClasses(): string {
    const classes = [
      'ui-feed-layout',
      `ui-feed-layout--${this.size}`,
    ];
    
    if (this.loading) {
      classes.push('ui-feed-layout--loading');
    }
    
    if (this.enableRefresh) {
      classes.push('ui-feed-layout--refresh-enabled');
    }
    
    return classes.join(' ');
  }

  private setupResizeObserver(): void {
    if (typeof ResizeObserver !== 'undefined') {
      this.resizeObserver = new ResizeObserver(() => {
        this.checkScrollPosition();
      });
      this.resizeObserver.observe(this.scrollContainer.nativeElement);
    }
  }
  
  handleScroll(event: Event): void {
    this.scrolled.emit(event);
    
    if (!this.enableInfiniteScroll || this.loading || this.hasError) {
      return;
    }
    
    if (this.scrollThrottleTimer) {
      clearTimeout(this.scrollThrottleTimer);
    }
    
    this.scrollThrottleTimer = window.setTimeout(() => {
      this.checkScrollPosition();
    }, 100);
  }
  
  private checkScrollPosition(): void {
    const container = this.scrollContainer.nativeElement;
    const scrollTop = container.scrollTop;
    const scrollHeight = container.scrollHeight;
    const clientHeight = container.clientHeight;
    
    if (scrollTop + clientHeight >= scrollHeight - this.scrollThreshold) {
      this.loadMore.emit();
    }
  }
  
  handleTouchStart(event: TouchEvent): void {
    if (!this.enableRefresh) return;
    
    this.touchStartY = event.touches[0].clientY;
  }
  
  handleTouchMove(event: TouchEvent): void {
    if (!this.enableRefresh || this.scrollContainer.nativeElement.scrollTop > 0) {
      return;
    }
    
    this.touchCurrentY = event.touches[0].clientY;
    const pullDistance = this.touchCurrentY - this.touchStartY;
    
    if (pullDistance > 0) {
      this.isPullingToRefresh.set(pullDistance > this.refreshThreshold);
      
      if (pullDistance > this.refreshThreshold) {
        event.preventDefault();
      }
    }
  }
  
  handleTouchEnd(event: TouchEvent): void {
    if (!this.enableRefresh) return;
    
    const pullDistance = this.touchCurrentY - this.touchStartY;
    
    if (pullDistance > this.refreshThreshold && !this.loading) {
      this.triggerRefresh();
    }
    
    this.isPullingToRefresh.set(false);
    this.touchStartY = 0;
    this.touchCurrentY = 0;
  }
  
  private triggerRefresh(): void {
    this.isRefreshing.set(true);
    this.refresh.emit();
    
    // Auto-reset refreshing state after 2 seconds if not manually reset
    setTimeout(() => {
      if (this.isRefreshing()) {
        this.isRefreshing.set(false);
      }
    }, 2000);
  }
  
  handleRetry(): void {
    this.retry.emit();
  }
  
  // Public method to reset refresh state
  resetRefresh(): void {
    this.isRefreshing.set(false);
  }
  
  // Public method to scroll to top
  scrollToTop(): void {
    this.scrollContainer.nativeElement.scrollTo({
      top: 0,
      behavior: 'smooth'
    });
  }
}