// app/core.jsx — routing, global app state, responsive hook. Exposes window.AppCtx + window.useApp.

const AppCtx = React.createContext(null);
const useApp = () => React.useContext(AppCtx);

// ---- hash routing ----
function parseHash() {
  let h = window.location.hash.replace(/^#/, '');
  if (!h || h === '/') return { name: 'home' };
  const [path, qs] = h.split('?');
  const query = {};
  if (qs) qs.split('&').forEach((p) => { const [k, v] = p.split('='); query[k] = decodeURIComponent(v || ''); });
  const seg = path.replace(/^\//, '').split('/');
  if (seg[0] === 'work' && seg[1]) return { name: 'work', id: seg[1], query };
  if (seg[0] === 'recording' && seg[1]) return seg[2] === 'review' ? { name: 'review', id: seg[1], query } : { name: 'recording', id: seg[1], query };
  if (seg[0] === 'search') return { name: 'search', query };
  if (seg[0] === 'signin') return { name: 'signin', query };
  if (seg[0] === 'signup') return { name: 'signup', query };
  if (seg[0] === 'me') return { name: 'me', query };
  return { name: 'home' };
}

function navigate(path) {
  window.location.hash = path;
  window.scrollTo(0, 0);
}

// ---- responsive ----
function useMediaQuery() {
  const get = () => ({ w: window.innerWidth, isMobile: window.innerWidth < 760, isNarrow: window.innerWidth < 1040 });
  const [m, setM] = React.useState(get);
  React.useEffect(() => {
    const on = () => setM(get());
    window.addEventListener('resize', on);
    return () => window.removeEventListener('resize', on);
  }, []);
  return m;
}

// ---- provider ----
function AppProvider({ children }) {
  const [route, setRoute] = React.useState(parseHash);
  const [user, setUser] = React.useState(null);
  const [myReviews, setMyReviews] = React.useState([]);
  const [toast, setToast] = React.useState(null);
  const media = useMediaQuery();

  React.useEffect(() => {
    const on = () => setRoute(parseHash());
    window.addEventListener('hashchange', on);
    return () => window.removeEventListener('hashchange', on);
  }, []);

  const showToast = React.useCallback((msg) => {
    setToast(msg);
    window.clearTimeout(showToast._t);
    showToast._t = window.setTimeout(() => setToast(null), 2600);
  }, []);

  const signIn = React.useCallback((name) => {
    const clean = (name || 'Listener').trim();
    const handle = '@' + clean.toLowerCase().replace(/[^a-z0-9]+/g, '.').replace(/^\.|\.$/g, '').slice(0, 16) || '@listener';
    setUser({ name: clean, handle, initial: clean[0] ? clean[0].toUpperCase() : 'L' });
  }, []);
  const signOut = React.useCallback(() => setUser(null), []);

  const addReview = React.useCallback((recording, { score, text, tags }) => {
    const r = recording;
    const review = {
      user: user ? user.handle : '@you', score, text, tags: tags || [], when: 'just now', likes: 0, mine: true,
    };
    r.fanReviews = [review, ...(r.fanReviews || [])];
    // nudge the aggregate fan score toward the new rating (cosmetic)
    r.fanCount = (r.fanCount || 0) + 1;
    setMyReviews((m) => [{ recording: r, score, text, tags, when: 'just now' }, ...m]);
  }, [user]);

  const value = {
    route, navigate, user, signIn, signOut, addReview, myReviews,
    toast, showToast, ...media,
  };
  return React.createElement(AppCtx.Provider, { value }, children);
}

Object.assign(window, { AppCtx, useApp, AppProvider, navigate });
