import {
  createBeatSaverAPI,
  type PlaylistFull,
  type PlaylistSearchParams,
  type PlaylistSearchResponse
} from '$lib/server/beatsaver';
import type { PageServerLoad } from './$types';

function parsePositiveInt(value: string | null, fallback: number): number {
  if (!value) return fallback;
  const parsed = Number.parseInt(value, 10);
  if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
  return parsed;
}

const SORT_ORDER_VALUES = ['Latest', 'Relevance', 'Curated'] as const;
type SortOrderOption = (typeof SORT_ORDER_VALUES)[number];
const SORT_ORDER_SET = new Set<string>(SORT_ORDER_VALUES);
const DEFAULT_SORT_ORDER: SortOrderOption = 'Latest';

function parseSortOrder(value: string | null): SortOrderOption {
  if (!value) return DEFAULT_SORT_ORDER;
  const normalized = value.trim();
  return SORT_ORDER_SET.has(normalized) ? (normalized as SortOrderOption) : DEFAULT_SORT_ORDER;
}

type SearchInfoShape = {
  page?: number;
  pages?: number;
  total?: number;
  size?: number;
  itemsPerPage?: number;
};

export const load: PageServerLoad = async ({ url, fetch, parent }) => {
  const parentData = await parent();
  const requestedPage = parsePositiveInt(url.searchParams.get('page'), 1);
  const pageIndex = requestedPage - 1;

  const api = createBeatSaverAPI(fetch);
  const MIN_MAPS = 3;
  const hasSubmitted = url.searchParams.has('submitted');
  const rawQuery = url.searchParams.get('q') ?? '';
  const query = rawQuery.trim();
  const rawSortOrder = url.searchParams.get('order') ?? url.searchParams.get('sortOrder');
  const sortOrder = parseSortOrder(rawSortOrder);
  const curated = url.searchParams.has('curated');
  const verified = url.searchParams.has('verified') ? true : hasSubmitted ? false : true;

  const searchState = {
    submitted: hasSubmitted,
    query,
    sortOrder,
    curated,
    verified
  };

  const searchParams: PlaylistSearchParams = {
    page: pageIndex,
    sortOrder,
    includeEmpty: false
  };

  if (query) {
    searchParams.query = query;
  }
  if (curated) {
    searchParams.curated = true;
  }
  if (verified) {
    searchParams.verified = true;
  }

  try {
    const response = (await api.searchPlaylists({
      ...searchParams
    })) as PlaylistSearchResponse<PlaylistFull>;
    const docsRaw = Array.isArray(response?.docs) ? response.docs : [];
    const docs = docsRaw.filter((playlist) => {
      const totalMaps = playlist?.stats?.totalMaps ?? 0;
      return Number.isFinite(totalMaps) && totalMaps >= MIN_MAPS;
    });
    const info = (response?.info && typeof response.info === 'object' ? (response.info as SearchInfoShape) : null) ?? null;

    const infoPage = typeof info?.page === 'number' ? info.page : pageIndex;
    const currentPage = infoPage + 1;
    const totalPages = typeof info?.pages === 'number' ? info.pages : null;
    const total = typeof info?.total === 'number' ? info.total : null;
    const pageSize = typeof info?.size === 'number'
      ? info.size
      : typeof info?.itemsPerPage === 'number'
        ? info.itemsPerPage
        : docs.length;

    return {
      ...parentData,
      playlists: docs,
      info,
      page: currentPage,
      totalPages,
      total,
      pageSize,
      error: null,
      search: searchState
    };
  } catch (err) {
    console.error('Failed to load BeatSaver playlists', err);
    return {
      ...parentData,
      playlists: [] as PlaylistFull[],
      info: null,
      page: requestedPage,
      totalPages: null,
      total: null,
      pageSize: 0,
      error: err instanceof Error ? err.message : 'Failed to load playlists',
      search: searchState
    };
  }
};


