import { isDealType } from '@/lib/deal-types';
import type { BrowseSort } from '@/lib/enums/search-sort';
import { BROWSE_SORT } from '@/lib/enums/search-sort';
import { clampInt } from '@/lib/url/queryCodec';
import type { UrlCodec } from '@/lib/url/useUrlFilterState';
import type { DealsUrlState } from './dealsCodec';

const BROWSE_SORTS = new Set<BrowseSort>(BROWSE_SORT);
const NON_DEFAULT_SORTS = new Set<BrowseSort>(BROWSE_SORT.filter((s) => s !== 'ending-soon'));

export interface MakeWhatsLeftCodecOpts {
  locale: 'he' | 'en';
  priceCeiling: number;
}

function basePath(locale: 'he' | 'en'): string {
  return locale === 'en' ? '/en/whats-left' : '/whats-left';
}

function parseBrowseSort(raw: string | null): BrowseSort {
  if (raw && BROWSE_SORTS.has(raw as BrowseSort)) return raw as BrowseSort;
  return 'ending-soon';
}

export function makeWhatsLeftCodec(opts: MakeWhatsLeftCodecOpts): UrlCodec<DealsUrlState> {
  const { locale, priceCeiling } = opts;
  const path = basePath(locale);

  return {
    parse(loc) {
      const sp = new URLSearchParams(loc.search);

      const typeRaw = sp.get('type');
      const type = typeRaw && isDealType(typeRaw) ? typeRaw : undefined;
      const catRaw = sp.get('cat');
      const catSlug = catRaw || undefined;
      const tagsRaw = sp.get('tags');
      const tagSlugs = tagsRaw ? tagsRaw.split(',').filter(Boolean) : [];
      const page = clampInt(sp.get('page'), {
        min: 1,
        max: Number.MAX_SAFE_INTEGER,
        fallback: 1,
      });
      const sort = parseBrowseSort(sp.get('sort'));
      const priceMin = clampInt(sp.get('priceMin'), {
        min: 0,
        max: Number.MAX_SAFE_INTEGER,
        fallback: 0,
      });
      const priceMax = clampInt(sp.get('priceMax'), {
        min: 0,
        max: Number.MAX_SAFE_INTEGER,
        fallback: 0,
      });

      return { type, catSlug, tagSlugs, page, sort, priceMin, priceMax };
    },

    build(state) {
      const sp = new URLSearchParams();
      const sort = parseBrowseSort(BROWSE_SORTS.has(state.sort as BrowseSort) ? state.sort : null);
      if (NON_DEFAULT_SORTS.has(sort)) sp.set('sort', sort);
      if (state.type) sp.set('type', state.type);
      if (state.catSlug) sp.set('cat', state.catSlug);
      if (state.tagSlugs.length) sp.set('tags', state.tagSlugs.join(','));
      if (state.page > 1) sp.set('page', String(state.page));
      if (state.priceMin > 0) sp.set('priceMin', String(state.priceMin));
      if (state.priceMax > 0 && state.priceMax < priceCeiling) {
        sp.set('priceMax', String(state.priceMax));
      }

      const qs = sp.toString();
      return qs ? `${path}?${qs}` : path;
    },
  };
}
