import { useCallback, useEffect, useRef, useState } from 'react';

export interface UsePromptHistoryOptions {
  /**
   * Storage key — should be product-scoped (e.g. `notes:chat:history`).
   * Pass `null` to disable persistence (in-memory only).
   */
  storageKey?: string | null;
  /** Maximum number of prompts retained. Default 50. */
  capacity?: number;
}

export interface UsePromptHistoryHelpers {
  /** The full history array, newest LAST. */
  history: string[];
  /** Append a prompt — dedupes consecutive duplicates + trims to capacity. */
  push: (prompt: string) => void;
  /** Clear all stored prompts. */
  clear: () => void;
  /** Cursor-up — returns the previous prompt (or null at the top). */
  prev: () => string | null;
  /** Cursor-down — returns the next prompt (or null at the bottom). */
  next: () => string | null;
  /** Reset the cursor — call when the user starts typing fresh. */
  resetCursor: () => void;
}

/**
 * `usePromptHistory` — bash-style ↑/↓ recall for prompt composers.
 *
 * Wave 9.E.4. Persistence is `localStorage` by default, scoped via
 * `storageKey`. Pass `null` for in-memory only (useful for tests +
 * SSR-prerender safety).
 */
export function usePromptHistory(
  options: UsePromptHistoryOptions = {},
): UsePromptHistoryHelpers {
  const { storageKey = 'bytelyst:prompt-history', capacity = 50 } = options;

  // Lazy initial value — never touches `localStorage` during SSR.
  const [history, setHistory] = useState<string[]>(() => {
    if (!storageKey || typeof window === 'undefined') return [];
    try {
      const raw = window.localStorage.getItem(storageKey);
      if (!raw) return [];
      const parsed = JSON.parse(raw);
      return Array.isArray(parsed) ? (parsed as string[]) : [];
    } catch {
      return [];
    }
  });
  // Cursor: -1 means 'not navigating'. >=0 indexes from the END (so 0
  // is the newest, history.length-1 is the oldest). This matches the
  // bash ↑ recall convention.
  const cursorRef = useRef(-1);

  useEffect(() => {
    if (!storageKey || typeof window === 'undefined') return;
    try {
      window.localStorage.setItem(storageKey, JSON.stringify(history));
    } catch {
      /* quota / disabled — ignore silently */
    }
  }, [storageKey, history]);

  const push = useCallback(
    (prompt: string) => {
      const trimmed = prompt.trim();
      if (!trimmed) return;
      setHistory((cur) => {
        // De-dupe consecutive duplicate.
        if (cur[cur.length - 1] === trimmed) return cur;
        const next = [...cur, trimmed];
        return next.length > capacity ? next.slice(next.length - capacity) : next;
      });
      cursorRef.current = -1;
    },
    [capacity],
  );

  const clear = useCallback(() => {
    setHistory([]);
    cursorRef.current = -1;
  }, []);

  const prev = useCallback((): string | null => {
    if (history.length === 0) return null;
    const newIdx = Math.min(history.length - 1, cursorRef.current + 1);
    cursorRef.current = newIdx;
    return history[history.length - 1 - newIdx] ?? null;
  }, [history]);

  const next = useCallback((): string | null => {
    if (history.length === 0) return null;
    if (cursorRef.current <= 0) {
      cursorRef.current = -1;
      return null;
    }
    cursorRef.current -= 1;
    return history[history.length - 1 - cursorRef.current] ?? null;
  }, [history]);

  const resetCursor = useCallback(() => {
    cursorRef.current = -1;
  }, []);

  return { history, push, clear, prev, next, resetCursor };
}
