/**
 * Hook for the initial BanGUI setup flow.
 *
 * Exposes the current setup completion status and a submission handler.
 */

import { useCallback, useEffect, useState } from "react";
import { ApiError } from "../api/client";
import { handleFetchError } from "../utils/fetchError";
import { getSetupStatus, submitSetup } from "../api/setup";
import type {
  SetupRequest,
  SetupStatusResponse,
} from "../types/setup";

export interface UseSetupResult {
  /** Known setup status, or null while loading. */
  status: SetupStatusResponse | null;
  /** Whether the initial status check is in progress. */
  loading: boolean;
  /** User-facing error message from the last status check. */
  error: string | null;
  /** Refresh the setup status from the backend. */
  refresh: () => Promise<void>;
  /** Whether a submit request is currently in flight. */
  submitting: boolean;
  /** User-facing error message from the last submit attempt. */
  submitError: string | null;
  /** Submit the initial setup payload. */
  submit: (payload: SetupRequest) => Promise<void>;
}

export function useSetup(): UseSetupResult {
  const [status, setStatus] = useState<SetupStatusResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [submitError, setSubmitError] = useState<string | null>(null);

  const refresh = useCallback(async (): Promise<void> => {
    setLoading(true);
    setError(null);

    try {
      const resp = await getSetupStatus();
      setStatus(resp);
    } catch (err: unknown) {
      const fallback = "Failed to fetch setup status";
      handleFetchError(err, setError, fallback);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void refresh();
  }, [refresh]);

  const submit = useCallback(async (payload: SetupRequest): Promise<void> => {
    setSubmitting(true);
    setSubmitError(null);

    try {
      await submitSetup(payload);
    } catch (err: unknown) {
      if (err instanceof ApiError) {
        setSubmitError(err.message);
      } else if (err instanceof Error) {
        setSubmitError(err.message);
      } else {
        setSubmitError("An unexpected error occurred.");
      }
      throw err;
    } finally {
      setSubmitting(false);
    }
  }, []);

  return {
    status,
    loading,
    error,
    refresh,
    submitting,
    submitError,
    submit,
  };
}
