import { useEffect, useState } from "react";
import { useClient } from "../AppConfig/AppConfig.tsx";
import { type Failure, Pending, type Success } from "../async-op.ts";
import type { CurrentUser, FailurePayload } from "../types.ts";

export function useFetchCurrentUser(options?: {
  /**
   * Optionally disable immediate fetch action.
   *
   * @default true
   */
  performFetch?: boolean;

  /**
   * Fetch new data every time the window is focused.
   *
   * Note that `performFetch` has to be enabled for this option to have an
   * effect — we are not revalidating when there is no fetch to do!
   *
   * @default false
   */
  revalidateOnFocus?: boolean;
}) {
  const { performFetch = true, revalidateOnFocus = false } = options ?? {};
  const client = useClient();
  const [latestAttemptTs, setLatestAttemptTs] = useState(Date.now());

  const [result, setResult] = useState<
    Success<CurrentUser> | Failure<FailurePayload> | Pending
  >(new Pending());

  // We are intentionally not using SWR in this case, as we don't want to deal
  // with caching or any of that business.
  useEffect(() => {
    if (performFetch) {
      const fetchUserAndStoreResult = async () => {
        const result = await client.getCurrentUser();
        setResult(result);
      };

      // Invoke the fetch action
      fetchUserAndStoreResult();

      if (revalidateOnFocus) {
        const controller = new AbortController();
        window.addEventListener("focus", fetchUserAndStoreResult, controller);

        return () => {
          controller.abort();
        };
      }
    }
  }, [client, latestAttemptTs, performFetch]);

  return {
    result,
    latestAttemptTs,
    reload: () => {
      setResult(new Pending());
      setLatestAttemptTs(Date.now());
    },
  };
}
