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

export type GalleryGridColumns = 1 | 2 | 3 | 4 | 5 | 6 | 'auto-fit';
export type GalleryGridGap = 'sm' | 'md' | 'lg';
export type GalleryGridObjectFit = 'cover' | 'contain' | 'fill' | 'scale-down';

export interface GalleryGridItem {
  id: string | number;
  src: string;
  alt?: string;
  title?: string;
  caption?: string;
  thumbnail?: string;
  loading?: boolean;
  selected?: boolean;
}

@Component({
  selector: 'ui-gallery-grid',
  standalone: true,
  imports: [CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  template: `
    <div 
      class="ui-gallery-grid"
      [class]="getGridClasses()"
      [class.ui-gallery-grid--masonry]="masonry"
      [attr.role]="'grid'"
      [attr.aria-label]="ariaLabel || 'Image gallery'">
      
      @if (items.length === 0) {
        <div class="ui-gallery-grid__empty" role="status" aria-live="polite">
          <div class="ui-gallery-grid__empty-icon" aria-hidden="true">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
              <circle cx="8.5" cy="8.5" r="1.5"/>
              <polyline points="21,15 16,10 5,21"/>
            </svg>
          </div>
          <div class="ui-gallery-grid__empty-text">
            {{ emptyText || 'No images to display' }}
          </div>
        </div>
      } @else {
        @for (item of items; track item.id) {
          <div 
            class="ui-gallery-grid__item"
            [class.ui-gallery-grid__item--loading]="item.loading"
            [class.ui-gallery-grid__item--selected]="item.selected"
            [attr.role]="'gridcell'"
            [attr.aria-label]="getItemAriaLabel(item)"
            [attr.tabindex]="disabled ? -1 : 0"
            (click)="handleItemClick(item, $event)"
            (keydown)="handleItemKeydown(item, $event)">
            
            @if (showZoomIndicator) {
              <div class="ui-gallery-grid__zoom-indicator" aria-hidden="true">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                  <circle cx="11" cy="11" r="8"/>
                  <path d="21 21l-4.35-4.35"/>
                  <circle cx="11" cy="11" r="3"/>
                </svg>
              </div>
            }
            
            <img 
              class="ui-gallery-grid__image"
              [class]="getImageClasses()"
              [src]="item.thumbnail || item.src"
              [alt]="item.alt || item.title || ''"
              [loading]="lazyLoading ? 'lazy' : 'eager'"
              (load)="handleImageLoad(item, $event)"
              (error)="handleImageError(item, $event)">
            
            @if (showOverlay && (item.title || item.caption)) {
              <div class="ui-gallery-grid__overlay">
                @if (item.title) {
                  <div class="ui-gallery-grid__title">{{ item.title }}</div>
                }
                @if (item.caption) {
                  <div class="ui-gallery-grid__caption">{{ item.caption }}</div>
                }
              </div>
            }
          </div>
        }
      }
    </div>
  `,
  styleUrl: './gallery-grid.component.scss'
})
export class GalleryGridComponent {
  @Input() items: GalleryGridItem[] = [];
  @Input() columns: GalleryGridColumns = 3;
  @Input() gap: GalleryGridGap = 'md';
  @Input() objectFit: GalleryGridObjectFit = 'cover';
  @Input() masonry = false;
  @Input() showOverlay = true;
  @Input() showZoomIndicator = true;
  @Input() lazyLoading = true;
  @Input() disabled = false;
  @Input() emptyText = 'No images to display';
  @Input() ariaLabel?: string;
  
  @Output() itemClick = new EventEmitter<{ item: GalleryGridItem; event: MouseEvent }>();
  @Output() itemSelect = new EventEmitter<GalleryGridItem>();
  @Output() imageLoad = new EventEmitter<{ item: GalleryGridItem; event: Event }>();
  @Output() imageError = new EventEmitter<{ item: GalleryGridItem; event: Event }>();

  handleItemClick(item: GalleryGridItem, event: MouseEvent): void {
    if (this.disabled || item.loading) {
      return;
    }
    
    event.preventDefault();
    this.itemClick.emit({ item, event });
    
    // Toggle selection if item supports it
    if (item.selected !== undefined) {
      this.itemSelect.emit(item);
    }
  }

  handleItemKeydown(item: GalleryGridItem, event: KeyboardEvent): void {
    if (this.disabled || item.loading) {
      return;
    }
    
    if (event.key === 'Enter' || event.key === ' ') {
      event.preventDefault();
      this.handleItemClick(item, event as any);
    }
    
    // Arrow key navigation
    if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {
      event.preventDefault();
      this.handleArrowNavigation(item, event.key);
    }
  }

  handleImageLoad(item: GalleryGridItem, event: Event): void {
    this.imageLoad.emit({ item, event });
  }

  handleImageError(item: GalleryGridItem, event: Event): void {
    this.imageError.emit({ item, event });
  }

  private handleArrowNavigation(currentItem: GalleryGridItem, key: string): void {
    const currentIndex = this.items.findIndex(item => item.id === currentItem.id);
    if (currentIndex === -1) return;
    
    let nextIndex: number;
    const columnsNum = typeof this.columns === 'number' ? this.columns : 3;
    
    switch (key) {
      case 'ArrowLeft':
        nextIndex = currentIndex > 0 ? currentIndex - 1 : this.items.length - 1;
        break;
      case 'ArrowRight':
        nextIndex = currentIndex < this.items.length - 1 ? currentIndex + 1 : 0;
        break;
      case 'ArrowUp':
        nextIndex = currentIndex - columnsNum;
        if (nextIndex < 0) {
          nextIndex = Math.floor((this.items.length - 1) / columnsNum) * columnsNum + (currentIndex % columnsNum);
          if (nextIndex >= this.items.length) {
            nextIndex -= columnsNum;
          }
        }
        break;
      case 'ArrowDown':
        nextIndex = currentIndex + columnsNum;
        if (nextIndex >= this.items.length) {
          nextIndex = currentIndex % columnsNum;
        }
        break;
      default:
        return;
    }
    
    // Focus the next item
    this.focusItem(nextIndex);
  }

  private focusItem(index: number): void {
    // This would ideally use ViewChild to focus the specific item
    // For now, we'll rely on the browser's tab navigation
    setTimeout(() => {
      const items = document.querySelectorAll('.ui-gallery-grid__item');
      const targetItem = items[index] as HTMLElement;
      if (targetItem) {
        targetItem.focus();
      }
    }, 0);
  }

  getGridClasses(): string {
    const columnsClass = typeof this.columns === 'number' 
      ? `ui-gallery-grid--columns-${this.columns}` 
      : `ui-gallery-grid--${this.columns}`;
    const gapClass = `ui-gallery-grid--gap-${this.gap}`;
    
    return `${columnsClass} ${gapClass}`;
  }

  getImageClasses(): string {
    return `ui-gallery-grid__image--${this.objectFit}`;
  }

  getItemAriaLabel(item: GalleryGridItem): string {
    const parts: string[] = [];
    
    if (item.title) {
      parts.push(item.title);
    }
    
    if (item.caption) {
      parts.push(item.caption);
    }
    
    if (item.alt) {
      parts.push(item.alt);
    }
    
    if (parts.length === 0) {
      parts.push('Gallery image');
    }
    
    if (item.selected) {
      parts.push('selected');
    }
    
    if (item.loading) {
      parts.push('loading');
    }
    
    return parts.join(', ');
  }

  // Utility methods for external use
  selectItem(itemId: string | number): void {
    const item = this.items.find(i => i.id === itemId);
    if (item) {
      item.selected = true;
      this.itemSelect.emit(item);
    }
  }

  deselectItem(itemId: string | number): void {
    const item = this.items.find(i => i.id === itemId);
    if (item) {
      item.selected = false;
    }
  }

  selectAll(): void {
    this.items.forEach(item => {
      item.selected = true;
    });
  }

  deselectAll(): void {
    this.items.forEach(item => {
      item.selected = false;
    });
  }

  getSelectedItems(): GalleryGridItem[] {
    return this.items.filter(item => item.selected);
  }
}