import { useCallback, useEffect, useMemo, useRef } from 'react';
import { useSearchParams } from 'react-router-dom';

/**
 * وضعیت لیست (جستجو، فیلترها، صفحه، تب) در query string زندگی می‌کند، نه در state
 * کامپوننت. دلیلش «بازگشت»‌ است: `navigate(-1)` همان URL قبلی را برمی‌گرداند، پس هر
 * چیزی که در URL باشد سرِ جایش برمی‌گردد و هر چیزی که در state باشد با remount می‌پرد.
 * سود جانبی: رفرش و اشتراک لینک هم همان نما را می‌دهد.
 *
 * مقدارِ برابرِ پیش‌فرض از URL حذف می‌شود تا آدرس تمیز بماند.
 */
export function useUrlState<T extends Record<string, string>>(defaults: T) {
  const [params, setParams] = useSearchParams();

  const state = useMemo(() => {
    const out = { ...defaults };
    (Object.keys(defaults) as (keyof T)[]).forEach((k) => {
      const raw = params.get(String(k));
      if (raw !== null) out[k] = raw as T[keyof T];
    });
    return out;
  }, [params, defaults]);

  // `setSearchParams` مثل setState صف نمی‌شود؛ دو فراخوانی در یک handler، اگر هر دو از
  // `params` فعلی شروع کنند، همدیگر را پاک می‌کنند. این ref آخرین مقدارِ نوشته‌شده را
  // نگه می‌دارد تا فراخوانی‌های پشت‌سرهم روی هم انباشته شوند.
  const latest = useRef(params);
  useEffect(() => { latest.current = params; }, [params]);

  /**
   * چند کلید را با هم می‌نویسد. `replace` پیش‌فرض است تا تایپ در فیلد جستجو
   * تاریخچه را پر نکند و یک بار «بازگشت» کاربر را از صفحه بیرون ببرد.
   */
  const setState = useCallback((patch: Partial<T>, opts?: { push?: boolean }) => {
    const next = new URLSearchParams(latest.current);
    Object.entries(patch).forEach(([k, v]) => {
      const value = v === undefined ? '' : String(v);
      if (value === '' || value === defaults[k as keyof T]) next.delete(k);
      else next.set(k, value);
    });

    latest.current = next;
    setParams(next, { replace: !opts?.push });
  }, [setParams, defaults]);

  return [state, setState] as const;
}

/** عدد صفحه از URL — همیشه ≥ ۱. */
export function pageOf(value: string): number {
  return Math.max(1, Number(value) || 1);
}
