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

export interface Tab {
  id: string;
  label: string;
  content?: any;
  closeable?: boolean;
  disabled?: boolean;
  lazyLoad?: boolean;
  icon?: string;
}

type TabSize = 'sm' | 'md' | 'lg';
type TabVariant = 'default' | 'filled' | 'pills' | 'underlined';
type TabPosition = 'top' | 'bottom' | 'left' | 'right';

@Component({
  selector: 'ui-tabs-container',
  standalone: true,
  imports: [CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  template: `
    <div 
      [ngClass]="getContainerClasses()"
      [attr.role]="'tablist'"
      [attr.aria-orientation]="position === 'left' || position === 'right' ? 'vertical' : 'horizontal'">
      
      <!-- Tab Navigation -->
      <div class="ui-tabs-container__nav" 
           [attr.role]="'tablist'">
        <div class="ui-tabs-container__nav-content"
             [class.ui-tabs-container__nav-content--dragging]="isDragging">
          @for (tab of tabs; track tab.id; let index = $index) {
            <button
              type="button"
              class="ui-tabs-container__tab"
              [class.ui-tabs-container__tab--active]="activeTabId() === tab.id"
              [class.ui-tabs-container__tab--disabled]="tab.disabled"
              [attr.role]="'tab'"
              [attr.aria-selected]="activeTabId() === tab.id"
              [attr.aria-controls]="'panel-' + tab.id"
              [attr.id]="'tab-' + tab.id"
              [attr.tabindex]="activeTabId() === tab.id ? 0 : -1"
              [disabled]="tab.disabled"
              [draggable]="reorderable && !tab.disabled"
              (click)="selectTab(tab.id)"
              (keydown)="handleTabKeydown($event, index)"
              (dragstart)="handleDragStart($event, index)"
              (dragover)="handleDragOver($event)"
              (drop)="handleDrop($event, index)"
              (dragend)="handleDragEnd()">
              
              @if (tab.icon) {
                <span class="ui-tabs-container__tab-icon" [attr.aria-hidden]="true">
                  {{ tab.icon }}
                </span>
              }
              
              <span class="ui-tabs-container__tab-label">{{ tab.label }}</span>
              
              @if (tab.closeable && !tab.disabled) {
                <button
                  type="button"
                  class="ui-tabs-container__tab-close"
                  [attr.aria-label]="'Close ' + tab.label"
                  (click)="closeTab($event, tab.id)">
                  ×
                </button>
              }
            </button>
          }
        </div>
        
        @if (scrollable && showScrollControls()) {
          <div class="ui-tabs-container__scroll-controls">
            <button
              type="button"
              class="ui-tabs-container__scroll-button ui-tabs-container__scroll-button--prev"
              [disabled]="!canScrollPrev()"
              [attr.aria-label]="'Scroll tabs left'"
              (click)="scrollTabs('prev')">
              ‹
            </button>
            <button
              type="button"
              class="ui-tabs-container__scroll-button ui-tabs-container__scroll-button--next"
              [disabled]="!canScrollNext()"
              [attr.aria-label]="'Scroll tabs right'"
              (click)="scrollTabs('next')">
              ›
            </button>
          </div>
        }
      </div>
      
      <!-- Tab Panels -->
      <div class="ui-tabs-container__content">
        <ng-content></ng-content>
      </div>
    </div>
  `,
  styleUrl: './tabs-container.component.scss'
})
export class TabsContainerComponent {
  @Input() tabs: Tab[] = [];
  @Input() size: TabSize = 'md';
  @Input() variant: TabVariant = 'default';
  @Input() position: TabPosition = 'top';
  @Input() scrollable = false;
  @Input() reorderable = false;
  @Input() lazyLoad = true;
  
  // Active tab management
  private _activeTabId = signal<string | null>(null);
  activeTabId = computed(() => this._activeTabId());
  
  // Drag and drop state
  isDragging = false;
  draggedIndex: number | null = null;
  
  @Output() tabSelected = new EventEmitter<string>();
  @Output() tabClosed = new EventEmitter<string>();
  @Output() tabsReordered = new EventEmitter<Tab[]>();
  
  ngOnInit() {
    // Set initial active tab if none is set
    if (!this.activeTabId() && this.tabs.length > 0) {
      const firstEnabledTab = this.tabs.find(tab => !tab.disabled);
      if (firstEnabledTab) {
        this._activeTabId.set(firstEnabledTab.id);
      }
    }
  }
  
  getContainerClasses(): Record<string, boolean> {
    return {
      'ui-tabs-container': true,
      [`ui-tabs-container--size-${this.size}`]: true,
      [`ui-tabs-container--variant-${this.variant}`]: true,
      [`ui-tabs-container--position-${this.position}`]: true,
      'ui-tabs-container--scrollable': this.scrollable
    };
  }
  
  selectTab(tabId: string): void {
    const tab = this.tabs.find(t => t.id === tabId);
    if (!tab || tab.disabled) return;
    
    this._activeTabId.set(tabId);
    this.tabSelected.emit(tabId);
  }
  
  closeTab(event: Event, tabId: string): void {
    event.stopPropagation();
    
    const tabIndex = this.tabs.findIndex(t => t.id === tabId);
    if (tabIndex === -1) return;
    
    // If closing active tab, select adjacent tab
    if (this.activeTabId() === tabId) {
      const remainingTabs = this.tabs.filter(t => t.id !== tabId && !t.disabled);
      if (remainingTabs.length > 0) {
        // Try to select next tab, or previous if no next
        const nextTab = this.tabs[tabIndex + 1];
        const prevTab = this.tabs[tabIndex - 1];
        
        if (nextTab && !nextTab.disabled) {
          this._activeTabId.set(nextTab.id);
        } else if (prevTab && !prevTab.disabled) {
          this._activeTabId.set(prevTab.id);
        } else {
          this._activeTabId.set(remainingTabs[0].id);
        }
      } else {
        this._activeTabId.set(null);
      }
    }
    
    this.tabClosed.emit(tabId);
  }
  
  handleTabKeydown(event: KeyboardEvent, index: number): void {
    const isHorizontal = this.position === 'top' || this.position === 'bottom';
    let newIndex = index;
    
    switch (event.key) {
      case 'ArrowRight':
        if (isHorizontal) {
          event.preventDefault();
          newIndex = this.getNextEnabledTabIndex(index, 1);
        }
        break;
      case 'ArrowLeft':
        if (isHorizontal) {
          event.preventDefault();
          newIndex = this.getNextEnabledTabIndex(index, -1);
        }
        break;
      case 'ArrowDown':
        if (!isHorizontal) {
          event.preventDefault();
          newIndex = this.getNextEnabledTabIndex(index, 1);
        }
        break;
      case 'ArrowUp':
        if (!isHorizontal) {
          event.preventDefault();
          newIndex = this.getNextEnabledTabIndex(index, -1);
        }
        break;
      case 'Home':
        event.preventDefault();
        newIndex = this.getNextEnabledTabIndex(-1, 1);
        break;
      case 'End':
        event.preventDefault();
        newIndex = this.getNextEnabledTabIndex(this.tabs.length, -1);
        break;
      case 'Delete':
        if (this.tabs[index].closeable) {
          event.preventDefault();
          this.closeTab(event, this.tabs[index].id);
        }
        break;
    }
    
    if (newIndex !== index && newIndex >= 0 && newIndex < this.tabs.length) {
      this.selectTab(this.tabs[newIndex].id);
      // Focus the new tab
      setTimeout(() => {
        const newTabElement = document.getElementById('tab-' + this.tabs[newIndex].id);
        newTabElement?.focus();
      });
    }
  }
  
  private getNextEnabledTabIndex(startIndex: number, direction: number): number {
    let index = startIndex + direction;
    
    while (index >= 0 && index < this.tabs.length) {
      if (!this.tabs[index].disabled) {
        return index;
      }
      index += direction;
    }
    
    // If we didn't find an enabled tab, wrap around
    if (direction > 0) {
      // Going forward, start from beginning
      for (let i = 0; i < startIndex; i++) {
        if (!this.tabs[i].disabled) {
          return i;
        }
      }
    } else {
      // Going backward, start from end
      for (let i = this.tabs.length - 1; i > startIndex; i--) {
        if (!this.tabs[i].disabled) {
          return i;
        }
      }
    }
    
    return startIndex; // Return original index if no other enabled tab found
  }
  
  // Drag and drop methods
  handleDragStart(event: DragEvent, index: number): void {
    if (!this.reorderable) return;
    
    this.isDragging = true;
    this.draggedIndex = index;
    
    if (event.dataTransfer) {
      event.dataTransfer.effectAllowed = 'move';
      event.dataTransfer.setData('text/plain', index.toString());
    }
  }
  
  handleDragOver(event: DragEvent): void {
    if (!this.reorderable || !this.isDragging) return;
    
    event.preventDefault();
    event.dataTransfer!.dropEffect = 'move';
  }
  
  handleDrop(event: DragEvent, dropIndex: number): void {
    if (!this.reorderable || this.draggedIndex === null) return;
    
    event.preventDefault();
    
    if (this.draggedIndex !== dropIndex) {
      const newTabs = [...this.tabs];
      const draggedTab = newTabs.splice(this.draggedIndex, 1)[0];
      newTabs.splice(dropIndex, 0, draggedTab);
      
      this.tabsReordered.emit(newTabs);
    }
    
    this.handleDragEnd();
  }
  
  handleDragEnd(): void {
    this.isDragging = false;
    this.draggedIndex = null;
  }
  
  // Scrolling methods
  showScrollControls(): boolean {
    // This would need actual element measurement in a real implementation
    return this.scrollable;
  }
  
  canScrollPrev(): boolean {
    // Implementation would check actual scroll position
    return true;
  }
  
  canScrollNext(): boolean {
    // Implementation would check actual scroll position
    return true;
  }
  
  scrollTabs(direction: 'prev' | 'next'): void {
    // Implementation would handle actual scrolling
    const navContent = document.querySelector('.ui-tabs-container__nav-content') as HTMLElement;
    if (navContent) {
      const scrollAmount = 200;
      navContent.scrollBy({
        left: direction === 'next' ? scrollAmount : -scrollAmount,
        behavior: 'smooth'
      });
    }
  }
}