import { useCallback, useEffect, useMemo, useRef } from "react";
import type { MessageNewService } from "@/socket";
import { MessageRepository } from "@/lib/db/repository";

/**
 * Persists messages to IndexedDB and loads cached messages on room change.
 * Does NOT replace the React state — acts as a side-effect cache layer.
 */
export function useMessageCache(roomId: string | undefined) {
  const lastPersistedSeq = useRef(0);

  /** Load cached messages from IndexedDB. Returns empty if none cached. */
  const loadCached = useCallback(
    async (limit = 50): Promise<MessageNewService[]> => {
      if (!roomId) return [];
      try {
        return await MessageRepository.getMessages(roomId, undefined, limit);
      } catch {
        return [];
      }
    },
    [roomId],
  );

  /** Persist a batch of messages to IndexedDB. */
  const persistBatch = useCallback(
    async (msgs: MessageNewService[]) => {
      if (!roomId || msgs.length === 0) return;
      try {
        await MessageRepository.saveMessages(roomId, msgs);
        const maxSeq = Math.max(...msgs.map((m) => m.seq));
        if (maxSeq > lastPersistedSeq.current) {
          lastPersistedSeq.current = maxSeq;
        }
      } catch {
        // IndexedDB write can fail silently
      }
    },
    [roomId],
  );

  /** Persist a single new message (from WS event). */
  const persistMessage = useCallback(
    async (msg: MessageNewService) => {
      if (!roomId) return;
      try {
        await MessageRepository.saveMessages(roomId, [msg]);
        if (msg.seq > lastPersistedSeq.current) {
          lastPersistedSeq.current = msg.seq;
        }
      } catch {
        // silent
      }
    },
    [roomId],
  );

  /** Get last known seq for this room from IndexedDB. */
  const getLastSeq = useCallback(async (): Promise<number> => {
    if (!roomId) return 0;
    try {
      return await MessageRepository.getLastSeq(roomId);
    } catch {
      return 0;
    }
  }, [roomId]);

  /** Clear cached messages for this room. */
  const clearCache = useCallback(async () => {
    if (!roomId) return;
    try {
      await MessageRepository.clearRoom(roomId);
      lastPersistedSeq.current = 0;
    } catch {
      // silent
    }
  }, [roomId]);

  // Prune old rooms on mount
  useEffect(() => {
    MessageRepository.prune().catch(() => {});
  }, []);

  return useMemo(
    () => ({ loadCached, persistBatch, persistMessage, getLastSeq, clearCache }),
    [loadCached, persistBatch, persistMessage, getLastSeq, clearCache],
  );
}
