// SPDX-License-Identifier: GPL-3.0-or-later

import { createContext, useCallback, useContext, useEffect, useState, type ReactNode } from 'react';
import {
  getUpdateStatus,
  checkForUpdates,
  setAutoUpdate as apiSetAutoUpdate,
  type UpdateState,
} from '../lib/api';

interface UpdateContextValue {
  state: UpdateState | null;
  loading: boolean;
  error: string | null;
  refresh: () => Promise<void>;
  install: () => Promise<void>;
  setAutoUpdate: (enabled: boolean) => Promise<void>;
}

const UpdateContext = createContext<UpdateContextValue | null>(null);

const POLL_INTERVAL_MS = 60 * 60 * 1000; // 1h foreground refresh; daemon polls more often

export function UpdateProvider({ children }: { children: ReactNode }) {
  const [state, setState] = useState<UpdateState | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const refresh = useCallback(async () => {
    try {
      const s = await getUpdateStatus();
      setState(s);
      setError(null);
    } catch (e) {
      // Updater being unavailable on the daemon is not a hard failure;
      // the banner just won't render and Settings will show "unsupported".
      setError(e instanceof Error ? e.message : String(e));
    } finally {
      setLoading(false);
    }
  }, []);

  const install = useCallback(async () => {
    const s = await checkForUpdates(true);
    setState(s);
  }, []);

  const setAutoUpdate = useCallback(async (enabled: boolean) => {
    await apiSetAutoUpdate(enabled);
    setState((prev) => (prev ? { ...prev, auto_update: enabled } : prev));
  }, []);

  useEffect(() => {
    void refresh();
    const id = window.setInterval(refresh, POLL_INTERVAL_MS);
    return () => window.clearInterval(id);
  }, [refresh]);

  return (
    <UpdateContext.Provider value={{ state, loading, error, refresh, install, setAutoUpdate }}>
      {children}
    </UpdateContext.Provider>
  );
}

export function useUpdates(): UpdateContextValue {
  const ctx = useContext(UpdateContext);
  if (!ctx) {
    throw new Error('useUpdates must be used within UpdateProvider');
  }
  return ctx;
}
