import type { ChatConversationSummary } from './types';

const CHAT_CLEARED_UNREAD_STORAGE_KEY = 'main-chat-panel:cleared-unread-response-at';

function canUseLocalStorage() {
  return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';
}

function readClearedUnreadActivityMap() {
  if (!canUseLocalStorage()) {
    return {} as Record<string, string>;
  }

  try {
    const raw = window.localStorage.getItem(CHAT_CLEARED_UNREAD_STORAGE_KEY);
    if (!raw) {
      return {} as Record<string, string>;
    }

    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
      return {} as Record<string, string>;
    }

    return Object.entries(parsed).reduce<Record<string, string>>((result, [sessionId, value]) => {
      if (typeof value === 'string' && value.trim()) {
        result[sessionId] = value;
      }

      return result;
    }, {});
  } catch {
    return {} as Record<string, string>;
  }
}

function writeClearedUnreadActivityMap(nextMap: Record<string, string>) {
  if (!canUseLocalStorage()) {
    return;
  }

  try {
    window.localStorage.setItem(CHAT_CLEARED_UNREAD_STORAGE_KEY, JSON.stringify(nextMap));
  } catch {
    // Ignore storage write failures and keep the in-memory merge behavior.
  }
}

function toConversationActivityTime(value: string | null | undefined) {
  if (!value) {
    return 0;
  }

  const parsed = Date.parse(value);
  return Number.isNaN(parsed) ? 0 : parsed;
}

export function getConversationActivityTime(
  item: Pick<ChatConversationSummary, 'lastMessageAt' | 'updatedAt'>,
) {
  const lastMessageActivityTime = toConversationActivityTime(item.lastMessageAt);

  if (lastMessageActivityTime > 0) {
    return lastMessageActivityTime;
  }

  return toConversationActivityTime(item.updatedAt);
}

export function rememberConversationUnreadCleared(
  item: Pick<ChatConversationSummary, 'sessionId' | 'lastMessageAt' | 'updatedAt'>,
) {
  const sessionId = item.sessionId.trim();
  const activityTime = getConversationActivityTime(item);

  if (!sessionId || activityTime <= 0) {
    return;
  }

  const nextMap = {
    ...readClearedUnreadActivityMap(),
    [sessionId]: new Date(activityTime).toISOString(),
  };

  writeClearedUnreadActivityMap(nextMap);
}

function getStoredClearedUnreadActivityTime(sessionId: string) {
  const storedValue = readClearedUnreadActivityMap()[sessionId];
  return toConversationActivityTime(storedValue);
}

export function resolveStoredConversationUnreadState(
  item: Pick<ChatConversationSummary, 'sessionId' | 'hasUnreadResponse' | 'lastMessageAt' | 'updatedAt'>,
) {
  if (!item.hasUnreadResponse) {
    return false;
  }

  const nextActivityTime = getConversationActivityTime(item);
  const storedClearedActivityTime = getStoredClearedUnreadActivityTime(item.sessionId.trim());

  if (storedClearedActivityTime > 0 && nextActivityTime > 0 && nextActivityTime <= storedClearedActivityTime) {
    return false;
  }

  return true;
}

export function resolveConversationUnreadMergeState(
  previousItem: Pick<ChatConversationSummary, 'sessionId' | 'hasUnreadResponse' | 'lastMessageAt' | 'updatedAt'>,
  nextItem: Pick<ChatConversationSummary, 'sessionId' | 'hasUnreadResponse' | 'lastMessageAt' | 'updatedAt'>,
) {
  if (!resolveStoredConversationUnreadState(nextItem)) {
    return false;
  }

  if (!previousItem.hasUnreadResponse && nextItem.hasUnreadResponse) {
    const previousActivityTime = getConversationActivityTime(previousItem);
    const nextActivityTime = getConversationActivityTime(nextItem);

    // Keep a locally-cleared unread state until a newer response message actually arrives.
    // `updatedAt` can move for read-sync or metadata updates, so `lastMessageAt` must win whenever available.
    if (previousActivityTime > 0 && nextActivityTime <= previousActivityTime) {
      return false;
    }
  }

  return nextItem.hasUnreadResponse;
}
