"use client";

/**
 * Page tabs change the URL (tabs spec, 03-structure-and-navigation §7.1; product owner, 29 Oct 2026): the active tab is
 * `?tab=` (or another key), so a tab can be bookmarked and shared and Back returns to the previous one. In-panel tabs
 * (inside a card, drawer or dialog) don't use this.
 *
 * The URL is read with useSyncExternalStore, so the server render (and the static export) sees no tab and the first
 * client render picks it up without a hydration mismatch or a Suspense boundary.
 */

import * as React from "react";

const CHANGED = "medora:tab-param";

const subscribe = (onChange: () => void) => {
  window.addEventListener("popstate", onChange);
  window.addEventListener(CHANGED, onChange);
  return () => {
    window.removeEventListener("popstate", onChange);
    window.removeEventListener(CHANGED, onChange);
  };
};

/** The tab in the URL (null when none) and a setter that pushes a history entry. */
export function useTabParam(key = "tab"): [string | null, (value: string) => void] {
  const value = React.useSyncExternalStore(
    subscribe,
    () => new URLSearchParams(window.location.search).get(key),
    () => null,
  );
  const set = React.useCallback(
    (next: string) => {
      const params = new URLSearchParams(window.location.search);
      if (params.get(key) === next) return;
      params.set(key, next);
      window.history.pushState(window.history.state, "", `${window.location.pathname}?${params}${window.location.hash}`);
      window.dispatchEvent(new Event(CHANGED));
    },
    [key],
  );
  return [value, set];
}

/** The tab to show: the URL's when it is one of `allowed`, otherwise `fallback` (an old link never opens a blank tab). */
export const validTab = (value: string | null, allowed: readonly string[], fallback: string) => (value && allowed.includes(value) ? value : fallback);
