import { STORAGE_KEY_GENERAL_SETTINGS, STORAGE_KEY_LAST_VIEWED_CHAT } from '../../core/constants';
import { getUserScopedStorageKey } from '../../core/storage/current-user-storage';
import { runWhenIdle } from '../../shared/rxjs';

export interface GeneralSettings {
  reopenLastViewedChat: boolean;
}

export const DEFAULT_GENERAL_SETTINGS: GeneralSettings = {
  reopenLastViewedChat: true
};

export interface LastViewedChatSnapshot {
  userId: string;
  roomId: string;
  channelId: string | null;
}

const pendingWrites = new Map<string, string | null>();

let flushScheduled = false;
let cancelScheduledFlush: (() => void) | null = null;

function scheduleStorageFlush(): void {
  if (flushScheduled) {
    return;
  }

  flushScheduled = true;
  cancelScheduledFlush = runWhenIdle(() => {
    flushScheduled = false;
    cancelScheduledFlush = null;

    const snapshot = Array.from(pendingWrites.entries());

    pendingWrites.clear();

    for (const [key, value] of snapshot) {
      try {
        if (value === null) {
          localStorage.removeItem(key);
        } else {
          localStorage.setItem(key, value);
        }
      } catch {
        // storage not available
      }
    }
  });
}

function scheduleStorageWrite(key: string, serialised: string): void {
  pendingWrites.set(key, serialised);
  scheduleStorageFlush();
}

function scheduleStorageRemove(key: string): void {
  pendingWrites.set(key, null);
  scheduleStorageFlush();
}

function readMaybePending(key: string): string | null {
  if (pendingWrites.has(key)) {
    return pendingWrites.get(key) ?? null;
  }

  try {
    return localStorage.getItem(key);
  } catch {
    return null;
  }
}

export function loadGeneralSettingsFromStorage(): GeneralSettings {
  try {
    const raw = readMaybePending(getUserScopedStorageKey(STORAGE_KEY_GENERAL_SETTINGS))
      ?? readMaybePending(STORAGE_KEY_GENERAL_SETTINGS);

    if (!raw) {
      return { ...DEFAULT_GENERAL_SETTINGS };
    }

    return normaliseGeneralSettings(JSON.parse(raw) as Partial<GeneralSettings>);
  } catch {
    return { ...DEFAULT_GENERAL_SETTINGS };
  }
}

export function saveGeneralSettingsToStorage(patch: Partial<GeneralSettings>): GeneralSettings {
  const nextSettings = normaliseGeneralSettings({
    ...loadGeneralSettingsFromStorage(),
    ...patch
  });

  scheduleStorageWrite(getUserScopedStorageKey(STORAGE_KEY_GENERAL_SETTINGS), JSON.stringify(nextSettings));

  return nextSettings;
}

export function loadLastViewedChatFromStorage(userId?: string | null): LastViewedChatSnapshot | null {
  try {
    const raw = readMaybePending(getUserScopedStorageKey(STORAGE_KEY_LAST_VIEWED_CHAT, userId))
      ?? readMaybePending(STORAGE_KEY_LAST_VIEWED_CHAT);

    if (!raw) {
      return null;
    }

    const snapshot = normaliseLastViewedChatSnapshot(JSON.parse(raw) as Partial<LastViewedChatSnapshot>);

    if (!snapshot) {
      return null;
    }

    if (userId && snapshot.userId !== userId) {
      return null;
    }

    return snapshot;
  } catch {
    return null;
  }
}

export function saveLastViewedChatToStorage(snapshot: LastViewedChatSnapshot): void {
  const normalised = normaliseLastViewedChatSnapshot(snapshot);

  if (!normalised) {
    return;
  }

  scheduleStorageWrite(
    getUserScopedStorageKey(STORAGE_KEY_LAST_VIEWED_CHAT, normalised.userId),
    JSON.stringify(normalised)
  );
}

export function clearLastViewedChatFromStorage(userId?: string | null): void {
  scheduleStorageRemove(getUserScopedStorageKey(STORAGE_KEY_LAST_VIEWED_CHAT, userId));
  scheduleStorageRemove(STORAGE_KEY_LAST_VIEWED_CHAT);
}

/** Force-flush any pending app-resume writes (e.g. before unload). */
export function flushAppResumeStorage(): void {
  if (cancelScheduledFlush) {
    cancelScheduledFlush();
    cancelScheduledFlush = null;
  }

  flushScheduled = false;

  const snapshot = Array.from(pendingWrites.entries());

  pendingWrites.clear();

  for (const [key, value] of snapshot) {
    try {
      if (value === null) {
        localStorage.removeItem(key);
      } else {
        localStorage.setItem(key, value);
      }
    } catch {
      // storage not available
    }
  }
}

function normaliseGeneralSettings(raw: Partial<GeneralSettings>): GeneralSettings {
  return {
    reopenLastViewedChat:
      typeof raw.reopenLastViewedChat === 'boolean'
        ? raw.reopenLastViewedChat
        : DEFAULT_GENERAL_SETTINGS.reopenLastViewedChat
  };
}

function normaliseLastViewedChatSnapshot(raw: Partial<LastViewedChatSnapshot>): LastViewedChatSnapshot | null {
  const userId = typeof raw.userId === 'string' ? raw.userId.trim() : '';
  const roomId = typeof raw.roomId === 'string' ? raw.roomId.trim() : '';
  const channelId = typeof raw.channelId === 'string'
    ? raw.channelId.trim() || null
    : null;

  if (!userId || !roomId) {
    return null;
  }

  return {
    userId,
    roomId,
    channelId
  };
}
