"use client";

import { ClientOnline } from "@/types/mutual/context/validations";
import { API_BASE_URL } from "@/config/config";
import { createContextHook } from "../hookFactory";

// Constants
const FETCH_TIMEOUT = 5000; // 5 seconds timeout

// Default online state to use when API calls fail
const DEFAULT_ONLINE_STATE: ClientOnline = {
  lastLogin: new Date(),
  lastLogout: new Date(),
  lastAction: new Date(),
  lastPage: "/",
  userType: "guest",
  lang: "en",
  timezone: "UTC",
};

/**
 * Fetches the current online state from the context API
 * @returns The online state or null if there was an error
 */
async function checkContextPageOnline(): Promise<ClientOnline | null> {
  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT);

    try {
      const result = await fetch(`${API_BASE_URL}/context/page/online`, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          "Cache-Control": "no-cache",
        },
        signal: controller.signal,
      });

      // Clear the timeout
      clearTimeout(timeoutId);

      if (!result.ok) {
        throw new Error(`HTTP error! Status: ${result.status}`);
      }

      const data = await result.json();

      if (data.status === 200 && data.data) {
        return data.data;
      } else {
        return null;
      }
    } catch (fetchError) {
      // Clear the timeout if it hasn't fired yet
      clearTimeout(timeoutId);

      if (
        fetchError instanceof DOMException &&
        fetchError.name === "AbortError"
      ) {
        return DEFAULT_ONLINE_STATE;
      }

      throw fetchError;
    }
  } catch (error) {
    if (error instanceof DOMException && error.name === "AbortError") {
      return DEFAULT_ONLINE_STATE;
    } else {
      console.error(
        "Error fetching online state:",
        error instanceof Error ? error.message : "Unknown error"
      );
      // Return default state instead of null for better user experience
      return DEFAULT_ONLINE_STATE;
    }
  }
}

/**
 * Updates the online state in the context API
 * @param setOnline The new online state to set
 * @returns The updated online state or null if there was an error
 */
async function setContextPageOnline(
  setOnline: ClientOnline
): Promise<ClientOnline | null> {
  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT);

    const result = await fetch(`${API_BASE_URL}/context/page/online`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Cache-Control": "no-cache",
      },
      body: JSON.stringify(setOnline),
      signal: controller.signal,
    });
    console.log("result", await result.json());

    // Clear the timeout
    clearTimeout(timeoutId);

    if (!result.ok) {
      throw new Error(`HTTP error! Status: ${result.status}`);
    }

    const data = await result.json();

    if (data.status === 200 && data.data) {
      return data.data;
    } else {
      return null;
    }
  } catch (error) {
    return null;
  }
}

// Create the online hook using the factory
const useContextOnline = createContextHook<ClientOnline>({
  endpoint: "/context/page/online",
  contextName: "online",
  enablePeriodicRefresh: true,
  refreshInterval: 5 * 60 * 1000, // 5 minutes
});

// Custom hook for online data with the expected interface
interface UseOnlineResult {
  onlineData: ClientOnline | null;
  isLoading: boolean;
  error: string | null;
  refreshOnline: () => Promise<void>;
  updateOnline: (newOnline: ClientOnline) => Promise<boolean>;
}

// Wrapper hook that adapts the generic hook to the expected interface
export function useOnline(): UseOnlineResult {
  const { data, isLoading, error, refresh, update } = useContextOnline();
  return {
    onlineData: data,
    isLoading,
    error,
    refreshOnline: refresh,
    updateOnline: update,
  };
}

export { checkContextPageOnline, setContextPageOnline };
