export const HIDDEN_MESSAGE_IDS_STORAGE_KEY = "qjclaw:hidden-message-ids:v1"

type HiddenMessageIdsBySession = Record<string, string[]>
type HiddenMessageStorage = Pick<Storage, "getItem" | "setItem">

function getDefaultStorage(): HiddenMessageStorage | undefined {
  try {
    return globalThis.localStorage
  } catch {
    return undefined
  }
}

function readHiddenMessageIds(storage = getDefaultStorage()): HiddenMessageIdsBySession {
  if (!storage) {
    return {}
  }

  try {
    const rawValue = storage.getItem(HIDDEN_MESSAGE_IDS_STORAGE_KEY)
    if (!rawValue) {
      return {}
    }

    const parsedValue = JSON.parse(rawValue) as unknown
    if (!parsedValue || typeof parsedValue !== "object" || Array.isArray(parsedValue)) {
      return {}
    }

    return Object.fromEntries(Object.entries(parsedValue).flatMap(([sessionId, messageIds]) => {
      if (!Array.isArray(messageIds)) {
        return []
      }

      const validMessageIds = messageIds.filter((messageId): messageId is string => typeof messageId === "string")
      return validMessageIds.length > 0 ? [[sessionId, [...new Set(validMessageIds)]]] : []
    }))
  } catch {
    return {}
  }
}

export function getHiddenMessageIds(sessionId: string, storage?: HiddenMessageStorage): Set<string> {
  return new Set(readHiddenMessageIds(storage)[sessionId] ?? [])
}

export function persistHiddenMessageId(sessionId: string, messageId: string, storage = getDefaultStorage()): void {
  if (!storage || !sessionId || !messageId) {
    return
  }

  const hiddenMessageIds = readHiddenMessageIds(storage)
  const sessionHiddenIds = hiddenMessageIds[sessionId] ?? []
  if (sessionHiddenIds.includes(messageId)) {
    return
  }

  try {
    storage.setItem(HIDDEN_MESSAGE_IDS_STORAGE_KEY, JSON.stringify({
      ...hiddenMessageIds,
      [sessionId]: [...sessionHiddenIds, messageId]
    }))
  } catch {
    // Current in-memory deletion still succeeds when persistence is unavailable.
  }
}
