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

export type ImageContainerSize = 'sm' | 'md' | 'lg' | 'xl';
export type ImageContainerAspectRatio = '1/1' | '4/3' | '16/9' | '3/2' | '2/1' | '3/4' | '9/16';
export type ImageContainerObjectFit = 'contain' | 'cover' | 'fill' | 'scale-down' | 'none';
export type ImageContainerShape = 'square' | 'rounded' | 'circle';

@Component({
  selector: 'ui-image-container',
  standalone: true,
  imports: [CommonModule],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  template: `
    <div 
      class="ui-image-container"
      [class]="getContainerClasses()"
      [class.ui-image-container--loading]="loading"
      [class.ui-image-container--error]="hasError"
      [class.ui-image-container--lazy]="lazy"
      [class.ui-image-container--loaded]="isLoaded"
      [style.--aspect-ratio]="aspectRatio"
      [attr.aria-label]="ariaLabel"
      (click)="handleClick($event)">
      
      @if (loading && !isLoaded) {
        <div class="ui-image-container__loading" aria-hidden="true">
          <div class="ui-image-container__spinner"></div>
        </div>
      }
      
      @if (hasError) {
        <div class="ui-image-container__error" role="img" [attr.aria-label]="errorAlt || 'Image failed to load'">
          <ng-content select="[slot='error']">
            <div class="ui-image-container__error-icon" aria-hidden="true">
              <svg width="24" height="24" 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>
            <span class="ui-image-container__error-text">Failed to load image</span>
          </ng-content>
        </div>
      } @else {
        <img 
          #imageElement
          class="ui-image-container__image"
          [class]="getImageClasses()"
          [src]="currentSrc"
          [alt]="alt || ''"
          [loading]="lazy ? 'lazy' : 'eager'"
          [style.object-fit]="objectFit"
          (load)="handleLoad($event)"
          (error)="handleError($event)"
          (loadstart)="handleLoadStart()"
          [attr.crossorigin]="crossorigin"
          [attr.referrerpolicy]="referrerPolicy"
          [attr.sizes]="sizes"
          [attr.srcset]="srcset">
      }

      @if (overlay) {
        <div class="ui-image-container__overlay">
          <ng-content select="[slot='overlay']"></ng-content>
        </div>
      }

      @if (caption) {
        <div class="ui-image-container__caption">
          <ng-content select="[slot='caption']">
            <span>{{ caption }}</span>
          </ng-content>
        </div>
      }
    </div>
  `,
  styleUrl: './image-container.component.scss'
})
export class ImageContainerComponent implements OnInit, OnDestroy {
  @Input() src!: string;
  @Input() alt = '';
  @Input() size: ImageContainerSize = 'md';
  @Input() aspectRatio: ImageContainerAspectRatio = '1/1';
  @Input() objectFit: ImageContainerObjectFit = 'cover';
  @Input() shape: ImageContainerShape = 'rounded';
  @Input() lazy = true;
  @Input() loading = false;
  @Input() placeholder?: string;
  @Input() caption?: string;
  @Input() overlay = false;
  @Input() ariaLabel?: string;
  @Input() errorAlt?: string;
  
  // Advanced image attributes
  @Input() srcset?: string;
  @Input() sizes?: string;
  @Input() crossorigin?: 'anonymous' | 'use-credentials';
  @Input() referrerPolicy?: 'no-referrer' | 'no-referrer-when-downgrade' | 'origin' | 'origin-when-cross-origin' | 'same-origin' | 'strict-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url';

  @Output() imageLoaded = new EventEmitter<Event>();
  @Output() imageError = new EventEmitter<Event>();
  @Output() imageClick = new EventEmitter<MouseEvent>();
  @Output() loadingChange = new EventEmitter<boolean>();

  private elementRef = inject(ElementRef);
  private intersectionObserver?: IntersectionObserver;
  
  hasError = false;
  isLoaded = false;
  currentSrc = '';

  ngOnInit(): void {
    this.initializeImage();
    if (this.lazy && this.supportsIntersectionObserver()) {
      this.setupLazyLoading();
    } else {
      this.loadImage();
    }
  }

  ngOnDestroy(): void {
    if (this.intersectionObserver) {
      this.intersectionObserver.disconnect();
    }
  }

  private initializeImage(): void {
    this.currentSrc = this.placeholder || this.src;
    this.hasError = false;
    this.isLoaded = false;
  }

  private setupLazyLoading(): void {
    if (!this.supportsIntersectionObserver()) {
      this.loadImage();
      return;
    }

    this.intersectionObserver = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            this.loadImage();
            this.intersectionObserver?.unobserve(entry.target);
          }
        });
      },
      {
        rootMargin: '50px 0px',
        threshold: 0.01
      }
    );

    this.intersectionObserver.observe(this.elementRef.nativeElement);
  }

  private loadImage(): void {
    if (this.src && !this.isLoaded && !this.hasError) {
      this.currentSrc = this.src;
      this.loading = true;
      this.loadingChange.emit(true);
    }
  }

  private supportsIntersectionObserver(): boolean {
    return 'IntersectionObserver' in window;
  }

  handleLoadStart(): void {
    this.loading = true;
    this.loadingChange.emit(true);
  }

  handleLoad(event: Event): void {
    this.loading = false;
    this.isLoaded = true;
    this.hasError = false;
    this.loadingChange.emit(false);
    this.imageLoaded.emit(event);
  }

  handleError(event: Event): void {
    this.loading = false;
    this.hasError = true;
    this.isLoaded = false;
    this.loadingChange.emit(false);
    this.imageError.emit(event);
  }

  handleClick(event: MouseEvent): void {
    if (!this.hasError) {
      this.imageClick.emit(event);
    }
  }

  // Method to retry loading failed images
  retryLoad(): void {
    this.hasError = false;
    this.isLoaded = false;
    this.loadImage();
  }

  getContainerClasses(): string {
    const aspectClass = `ui-image-container--aspect-${this.aspectRatio.replace('/', '-')}`;
    const sizeClass = `ui-image-container--size-${this.size}`;
    const shapeClass = `ui-image-container--shape-${this.shape}`;
    
    return `ui-image-container ${sizeClass} ${aspectClass} ${shapeClass}`;
  }

  getImageClasses(): string {
    const fitClass = `ui-image-container__image--fit-${this.objectFit}`;
    return `ui-image-container__image ${fitClass}`;
  }
}