/**
 * What Piggy is looking at, published by the page and read by the dock.
 *
 * The shape itself is `PiggyChatContext` in @pig/core, because it crosses four
 * process boundaries; this module is only the browser-side plumbing for
 * deciding *which* context is in force.
 *
 * Two ways to answer that, and the precedence between them is the whole point:
 *
 *   ambient  — the dock is open on some page and nobody said otherwise, so the
 *              context is `{ type: 'page', route }` derived from the router. A
 *              page can publish something better with `usePiggyContext`.
 *   explicit — a component passed a context prop, because the user pressed
 *              "Ask Piggy" on a specific row. That is a record context and it
 *              must win: the ambient page context is a guess, and a guess must
 *              never displace the thing the user actually pointed at.
 */
import {
  createContext,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import { useLocation } from 'react-router-dom';
import { toPiggyPageRoute, type PiggyChatContext } from '@pig/core';

interface PiggyContextValue {
  /** What a page has published, if anything. */
  published: PiggyChatContext | undefined;
  publish: (context: PiggyChatContext | undefined) => void;
}

const PiggyContextContext = createContext<PiggyContextValue | null>(null);

export function PiggyContextProvider({ children }: { children: ReactNode }) {
  const [published, setPublished] = useState<PiggyChatContext | undefined>(undefined);
  const value = useMemo(() => ({ published, publish: setPublished }), [published]);
  return <PiggyContextContext.Provider value={value}>{children}</PiggyContextContext.Provider>;
}

/**
 * Publish a context for as long as this component is mounted.
 *
 * Clearing on unmount matters: without it, navigating away from a record page
 * leaves Piggy still holding that record's id, and it answers questions about
 * a row that is no longer on screen.
 */
export function usePiggyContext(value: PiggyChatContext | undefined): void {
  const context = useContext(PiggyContextContext);
  const publish = context?.publish;
  // Serialised rather than passed by reference: call sites build the object
  // inline, so a reference dependency re-publishes on every render.
  const key = value ? JSON.stringify(value) : '';

  useEffect(() => {
    if (!publish) return;
    publish(key ? (JSON.parse(key) as PiggyChatContext) : undefined);
    return () => publish(undefined);
  }, [publish, key]);
}

/**
 * The context in force right now: whatever a page published, else the route.
 *
 * Safe outside the provider — it falls back to the route alone — because the
 * unauthenticated screens render without the shell.
 */
export function usePiggyCurrentContext(): PiggyChatContext {
  const context = useContext(PiggyContextContext);
  const { pathname } = useLocation();
  const route = toPiggyPageRoute(pathname);
  return context?.published ?? { type: 'page', route };
}
