import { ChangeDetectionStrategy, Component, ElementRef, ViewChild, computed, effect, inject, input, output, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { TranslatePipe } from '../../../i18n/translate.pipe';
import { TranslateService } from '../../../i18n/translate.service';
import { MediaLibraryFacade } from '../../../features/backoffice/media/facade/media-library.facade';
import { MediaAsset, MediaAssetKind } from '../../../core/media/models/media-asset.model';
import { ButtonComponent } from '../../ui/button/button.component';
import { InputComponent } from '../../ui/input/input.component';
import { CardComponent } from '../../ui/card/card.component';
import { EmptyStateComponent } from '../../ui/empty-state/empty-state.component';
import { DialogComponent } from '../../ui/dialog/dialog.component';
import { PaginationComponent } from '../../ui/pagination/pagination.component';
import { SkeletonComponent } from '../../ui/skeleton/skeleton.component';
import { SelectComponent, SelectOption } from '../../ui/select/select.component';

const PAGE_SIZE = 24;

@Component({
  selector: 'app-media-picker',
  standalone: true,
  imports: [
    FormsModule,
    TranslatePipe,
    ButtonComponent,
    InputComponent,
    CardComponent,
    EmptyStateComponent,
    DialogComponent,
    PaginationComponent,
    SkeletonComponent,
    SelectComponent,
  ],
  templateUrl: './media-picker.component.html',
  styleUrl: './media-picker.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MediaPickerComponent {
  readonly open = input(false);

  readonly selected = output<MediaAsset>();
  readonly closed = output<void>();

  protected readonly facade = inject(MediaLibraryFacade);
  private readonly translate = inject(TranslateService);

  @ViewChild('fileInput') private fileInput?: ElementRef<HTMLInputElement>;

  protected readonly totalPages = () => Math.max(1, Math.ceil(this.facade.total() / PAGE_SIZE));
  protected readonly focusedIndex = signal(0);

  protected readonly kindOptions = computed<SelectOption[]>(() => [
    { value: 'all', label: this.translate.t('mediaLibrary.allTypes') },
    { value: 'image', label: this.translate.t('mediaLibrary.typeImage') },
    { value: 'svg', label: this.translate.t('mediaLibrary.typeSvg') },
    { value: 'pdf', label: this.translate.t('mediaLibrary.typePdf') },
  ]);

  setKind(value: string): void {
    this.facade.setKind(value === 'all' ? null : (value as MediaAssetKind));
  }

  showRecentOnly(): void {
    this.facade.setSort('recent');
    this.facade.setFolder(null);
    this.facade.setSearch('');
  }

  protected onGridKeydown(event: KeyboardEvent): void {
    const count = this.facade.items().length;
    if (count === 0) {
      return;
    }
    const columns = Math.max(1, Math.floor((event.currentTarget as HTMLElement).clientWidth / 150));
    if (event.key === 'ArrowRight') {
      event.preventDefault();
      this.focusedIndex.set(Math.min(count - 1, this.focusedIndex() + 1));
    } else if (event.key === 'ArrowLeft') {
      event.preventDefault();
      this.focusedIndex.set(Math.max(0, this.focusedIndex() - 1));
    } else if (event.key === 'ArrowDown') {
      event.preventDefault();
      this.focusedIndex.set(Math.min(count - 1, this.focusedIndex() + columns));
    } else if (event.key === 'ArrowUp') {
      event.preventDefault();
      this.focusedIndex.set(Math.max(0, this.focusedIndex() - columns));
    } else if (event.key === 'Enter') {
      const asset = this.facade.items()[this.focusedIndex()];
      if (asset) {
        this.pick(asset);
      }
    }
  }

  constructor() {
    // MediaLibraryFacade is a root-provided singleton shared by every
    // app-media-picker instance on the page (a form with several image
    // fields renders one instance each). Loading unconditionally in
    // ngOnInit meant every instance fetched on mount regardless of whether
    // its dialog was ever opened, and search/folder/page state from one
    // dialog leaked into whichever picker was opened next. Reset the
    // shared filters and (re)load only when this instance's dialog
    // actually opens.
    effect(() => {
      if (this.open()) {
        this.facade.search.set('');
        this.facade.folder.set(null);
        this.facade.kind.set(null);
        this.facade.page.set(1);
        this.focusedIndex.set(0);
        void this.facade.load();
      }
    });
  }

  protected triggerFileInput(): void {
    this.fileInput?.nativeElement.click();
  }

  protected async onFileSelected(event: Event): Promise<void> {
    const input = event.target as HTMLInputElement;
    const file = input.files?.[0];
    input.value = '';
    if (!file) {
      return;
    }
    await this.facade.upload(file);
  }

  protected pick(asset: MediaAsset): void {
    this.selected.emit(asset);
    this.closed.emit();
  }

  protected requestClose(): void {
    this.closed.emit();
  }
}
