import { PRICE_UNITS, type PriceUnit } from '@/services/catalog/types';
import { SEARCH_PAGE_SIZE } from './constants';
import type { NurseGender, NurseSearchFilters } from './types';

/**
 * Single source of truth for the C1 → C2 filter **query string** (snake_case, matching the b7 contract
 * params), so C1 (which writes the URL) and C2 (which reads it via `useSearchParams`) never drift. The
 * URL is the deep-linkable, back/forward-safe carrier of the filter set; C2 turns it back into a
 * `NurseSearchFilters`, which is what becomes the React Query cache key.
 */

/** Minimal read surface shared by `URLSearchParams` and Next's `ReadonlyURLSearchParams`. */
interface ParamReader {
  get(name: string): string | null;
}

const GENDERS: readonly NurseGender[] = ['male', 'female'];

function parsePositiveInt(raw: string | null): number | undefined {
  if (raw == null) return undefined;
  const value = Number(raw);
  return Number.isInteger(value) && value > 0 ? value : undefined;
}

function parseGender(raw: string | null): NurseGender | undefined {
  return raw != null && GENDERS.includes(raw as NurseGender) ? (raw as NurseGender) : undefined;
}

function parsePriceUnit(raw: string | null): PriceUnit | undefined {
  return raw != null && PRICE_UNITS.includes(raw as PriceUnit) ? (raw as PriceUnit) : undefined;
}

/** IRR digit-string or undefined (never a float; leaves bogus input out). */
function parseIrrString(raw: string | null): string | undefined {
  return raw != null && /^\d+$/.test(raw) ? raw : undefined;
}

/** Serialise a filter set to snake_case URL params, omitting every absent optional filter. */
export function filtersToSearchParams(filters: NurseSearchFilters): URLSearchParams {
  const params = new URLSearchParams();
  params.set('service_category_id', String(filters.serviceCategoryId));
  params.set('city_id', String(filters.cityId));
  if (filters.districtId != null) params.set('district_id', String(filters.districtId));
  if (filters.nurseGender) params.set('nurse_gender', filters.nurseGender);
  if (filters.priceMin) params.set('min_price', filters.priceMin);
  if (filters.priceMax) params.set('max_price', filters.priceMax);
  if (filters.priceUnit) params.set('price_unit', filters.priceUnit);
  return params;
}

/**
 * Rebuild a `NurseSearchFilters` from URL params. `serviceCategoryId`/`cityId` fall back to `0` when
 * absent/invalid — the query hook is disabled until both are `> 0`, so an incomplete URL is inert
 * rather than an error. Sort is always rating (MVP); page/pageSize reset to the first page.
 */
export function searchParamsToFilters(params: ParamReader): NurseSearchFilters {
  return {
    serviceCategoryId: parsePositiveInt(params.get('service_category_id')) ?? 0,
    cityId: parsePositiveInt(params.get('city_id')) ?? 0,
    districtId: parsePositiveInt(params.get('district_id')),
    nurseGender: parseGender(params.get('nurse_gender')),
    priceMin: parseIrrString(params.get('min_price')),
    priceMax: parseIrrString(params.get('max_price')),
    priceUnit: parsePriceUnit(params.get('price_unit')),
    sort: 'rating',
    page: 1,
    pageSize: SEARCH_PAGE_SIZE,
  };
}
