import { useEffect, useRef, useState } from 'react';
import type { FileClient } from '../client/client.js';
import { useShadeFilesContext } from './ShadeFilesProvider.js';

export interface UseShadeFilesResult {
  fs: FileClient | null;
  isLoading: boolean;
  error: unknown;
  /** True after a successful `stat('/')` probe; false until proven online. */
  isOnline: boolean;
  /** Force a re-probe. */
  refresh(): void;
}

export interface UseShadeFilesOptions {
  /** Probe interval (ms) for `isOnline`. Default 30_000. Disable with 0. */
  probeIntervalMs?: number;
}

/**
 * Get a typed `FileClient` for `peer`. Memoizes per (shade, peer) so
 * multiple components sharing the same peer reuse the same client.
 */
export function useShadeFiles(
  peer: string,
  opts: UseShadeFilesOptions = {},
): UseShadeFilesResult {
  const { files } = useShadeFilesContext();
  const [fs, setFs] = useState<FileClient | null>(null);
  const [error, setError] = useState<unknown>(null);
  const [isOnline, setIsOnline] = useState(false);
  const [probeTick, setProbeTick] = useState(0);
  const cancelledRef = useRef(false);

  useEffect(() => {
    cancelledRef.current = false;
    let mounted = true;
    setError(null);
    setFs(null);
    files
      .client(peer)
      .then((client) => {
        if (!mounted) {
          client.close();
          return;
        }
        setFs(client);
      })
      .catch((err) => {
        if (mounted) setError(err);
      });
    return () => {
      mounted = false;
      cancelledRef.current = true;
    };
  }, [files, peer]);

  // Periodic probe: stat('/') as a cheap reachability check.
  useEffect(() => {
    if (fs === null) return undefined;
    const intervalMs = opts.probeIntervalMs ?? 30_000;
    let cancelled = false;
    const probe = (): void => {
      fs.stat('/')
        .then(() => {
          if (!cancelled) setIsOnline(true);
        })
        .catch(() => {
          if (!cancelled) setIsOnline(false);
        });
    };
    probe();
    if (intervalMs <= 0) return () => undefined;
    const timer = setInterval(probe, intervalMs);
    return () => {
      cancelled = true;
      clearInterval(timer);
    };
  }, [fs, opts.probeIntervalMs, probeTick]);

  return {
    fs,
    isLoading: fs === null && error === null,
    error,
    isOnline,
    refresh: () => setProbeTick((t) => t + 1),
  };
}
