import { useCallback, useEffect, useState } from 'react';
import { EpKey, load } from './api';

interface LoadState<T> {
  data?: T;
  err?: string;
  loading: boolean;
}

/* Load one or more endpoints; refresh() re-runs after the cache is cleared. */
export function useLoad<T>(fn: () => Promise<T>): LoadState<T> & { refresh: () => void } {
  const [state, setState] = useState<LoadState<T>>({ loading: true });
  const [tick, setTick] = useState(0);

  useEffect(() => {
    let live = true;
    setState((s) => ({ ...s, loading: true, err: undefined }));
    fn()
      .then((data) => live && setState({ data, loading: false }))
      .catch((e) => {
        if (!live) return;
        const msg = e instanceof Error ? e.message : String(e);
        if (msg !== 'unauthorized') setState({ err: msg, loading: false });
      });
    return () => {
      live = false;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tick]);

  const refresh = useCallback(() => setTick((t) => t + 1), []);
  return { ...state, refresh };
}

/* Load several endpoints; failures resolve to null per-key (Today screen). */
export function loadAll<T extends Record<string, EpKey>>(
  spec: T,
): Promise<{ [K in keyof T]: unknown | null }> {
  const keys = Object.keys(spec) as (keyof T)[];
  return Promise.all(
    keys.map((k) => load(spec[k]).catch(() => null)),
  ).then((vals) => {
    const out = {} as { [K in keyof T]: unknown | null };
    keys.forEach((k, i) => (out[k] = vals[i]));
    return out;
  });
}
