/**
 * @file useChatOverlay.ts
 * @description Hook for managing the global chat overlay state
 */

import { useState, useEffect, useCallback, useRef } from "react";
import { safeJsonParse, isChatOverlayState } from "@/lib/utils/safe-json";

interface ChatOverlayState {
  isOpen: boolean;
  isMinimized: boolean;
}

export interface UseChatOverlayOptions {
  onStorageError?: (message: string) => void;
}

interface UseChatOverlayResult extends ChatOverlayState {
  open: () => void;
  close: () => void;
  minimize: () => void;
  expand: () => void;
  toggle: () => void;
  toggleMinimize: () => void;
}

const STORAGE_KEY = "chatOverlayState";

const DEFAULT_STATE: ChatOverlayState = {
  isOpen: false,
  isMinimized: false,
};

/**
 * Get a user-friendly error message for localStorage failures
 */
function getStorageErrorMessage(error: unknown): string {
  if (error instanceof DOMException) {
    switch (error.name) {
      case "QuotaExceededError":
        return "Storage is full. Chat state may not persist across page refreshes.";
      case "SecurityError":
        return "Storage is unavailable in this browser mode. Chat state will not persist.";
      case "InvalidStateError":
        return "Storage is disabled. Chat state will not persist across page refreshes.";
    }
  }
  return "Unable to save chat state. It may not persist across page refreshes.";
}

/**
 * Load state from localStorage with runtime type validation
 */
function loadState(): ChatOverlayState {
  if (typeof window === "undefined") {
    return DEFAULT_STATE;
  }

  try {
    const stored = window.localStorage.getItem(STORAGE_KEY);
    if (stored) {
      return safeJsonParse(stored, isChatOverlayState, DEFAULT_STATE);
    }
  } catch (error) {
    console.warn("Failed to load chat overlay state from localStorage:", error);
  }

  return DEFAULT_STATE;
}

/**
 * Save state to localStorage, notifying on error (once per error type)
 */
function saveState(
  state: ChatOverlayState,
  onStorageError: ((message: string) => void) | undefined,
  notifiedErrors: Set<string>
): void {
  if (typeof window === "undefined") {
    return;
  }

  try {
    window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
  } catch (error) {
    const errorName =
      error instanceof DOMException
        ? error.name
        : error instanceof Error
          ? error.constructor.name
          : "UnknownError";
    console.warn("Failed to save chat overlay state to localStorage:", error);

    if (onStorageError && !notifiedErrors.has(errorName)) {
      notifiedErrors.add(errorName);
      onStorageError(getStorageErrorMessage(error));
    }
  }
}

/**
 * Custom hook for managing chat overlay state
 * Persists state to localStorage for consistency across page refreshes.
 * Enforces invariant: cannot be minimized when closed.
 */
export function useChatOverlay(options: UseChatOverlayOptions = {}): UseChatOverlayResult {
  const { onStorageError } = options;
  const [state, setState] = useState<ChatOverlayState>(loadState);
  const notifiedErrorsRef = useRef<Set<string>>(new Set());
  const onStorageErrorRef = useRef(onStorageError);
  onStorageErrorRef.current = onStorageError;

  // Persist state changes to localStorage
  useEffect(() => {
    saveState(state, onStorageErrorRef.current, notifiedErrorsRef.current);
  }, [state]);

  const open = useCallback(() => {
    setState({ isOpen: true, isMinimized: false });
  }, []);

  const close = useCallback(() => {
    setState({ isOpen: false, isMinimized: false });
  }, []);

  const minimize = useCallback(() => {
    setState((prev) => (prev.isOpen ? { ...prev, isMinimized: true } : prev));
  }, []);

  const expand = useCallback(() => {
    setState((prev) => ({ ...prev, isMinimized: false }));
  }, []);

  const toggle = useCallback(() => {
    setState((prev) => {
      const newIsOpen = !prev.isOpen;
      return { isOpen: newIsOpen, isMinimized: newIsOpen ? prev.isMinimized : false };
    });
  }, []);

  const toggleMinimize = useCallback(() => {
    setState((prev) => (prev.isOpen ? { ...prev, isMinimized: !prev.isMinimized } : prev));
  }, []);

  return {
    ...state,
    open,
    close,
    minimize,
    expand,
    toggle,
    toggleMinimize,
  };
}
