import { sortAlbums } from '$lib/utils/album-utils';
import { normalizeSearchString } from '$lib/utils/string-utils';
import type { AlbumResponseDto } from '@immich/sdk';
import { t } from 'svelte-i18n';
import { get } from 'svelte/store';

export const SCROLL_PROPERTIES: ScrollIntoViewOptions = { block: 'center', behavior: 'smooth' };

export enum AlbumModalRowType {
  SECTION = 'section',
  MESSAGE = 'message',
  NEW_ALBUM = 'newAlbum',
  ALBUM_ITEM = 'albumItem',
}

export type AlbumModalRow = {
  type: AlbumModalRowType;
  selected?: boolean;
  multiSelected?: boolean;
  text?: string;
  album?: AlbumResponseDto;
};

export const isSelectableRowType = (type: AlbumModalRowType) =>
  type === AlbumModalRowType.NEW_ALBUM || type === AlbumModalRowType.ALBUM_ITEM;

const $t = get(t);

export class AlbumModalRowConverter {
  private readonly sortBy: string;
  private readonly orderBy: string;

  constructor(sortBy: string, orderBy: string) {
    this.sortBy = sortBy;
    this.orderBy = orderBy;
  }

  toModalRows(
    search: string,
    recentAlbums: AlbumResponseDto[],
    albums: AlbumResponseDto[],
    selectedRowIndex: number,
    multiSelectedAlbumIds: string[],
  ): AlbumModalRow[] {
    // only show recent albums if no search was entered
    const recentAlbumsToShow = search.length === 0 ? recentAlbums : [];
    const rows: AlbumModalRow[] = [{ type: AlbumModalRowType.NEW_ALBUM, selected: selectedRowIndex === 0 }];

    const filteredAlbums = sortAlbums(
      search.length > 0 && albums.length > 0
        ? albums.filter((album) => {
            return normalizeSearchString(album.albumName).includes(normalizeSearchString(search));
          })
        : albums,
      { sortBy: this.sortBy, orderBy: this.orderBy },
    );

    if (filteredAlbums.length > 0) {
      if (recentAlbumsToShow.length > 0) {
        rows.push({ type: AlbumModalRowType.SECTION, text: $t('recent').toUpperCase() });
        const selectedOffsetDueToNewAlbumRow = 1;
        for (const [i, album] of recentAlbums.entries()) {
          rows.push({
            type: AlbumModalRowType.ALBUM_ITEM,
            selected: selectedRowIndex === i + selectedOffsetDueToNewAlbumRow,
            multiSelected: multiSelectedAlbumIds.includes(album.id),
            album,
          });
        }
      }

      rows.push({
        type: AlbumModalRowType.SECTION,
        text: (search.length === 0 ? $t('all_albums') : $t('albums')).toUpperCase(),
      });

      const selectedOffsetDueToNewAndRecents = 1 + recentAlbumsToShow.length;
      for (const [i, album] of filteredAlbums.entries()) {
        rows.push({
          type: AlbumModalRowType.ALBUM_ITEM,
          selected: selectedRowIndex === i + selectedOffsetDueToNewAndRecents,
          multiSelected: multiSelectedAlbumIds.includes(album.id),
          album,
        });
      }
    } else if (albums.length > 0) {
      rows.push({ type: AlbumModalRowType.MESSAGE, text: $t('no_albums_with_name_yet') });
    } else {
      rows.push({ type: AlbumModalRowType.MESSAGE, text: $t('no_albums_yet') });
    }
    return rows;
  }
}
