import { Injectable } from '@angular/core';
import { STORAGE_KEY_NOTIFICATION_SETTINGS } from '../../../../core/constants';
import { createDefaultNotificationSettings, type NotificationsSettings } from '../../domain/models/notification.model';

@Injectable({ providedIn: 'root' })
export class NotificationSettingsStorageService {
  load(): NotificationsSettings {
    const fallback = createDefaultNotificationSettings();
    const raw = localStorage.getItem(STORAGE_KEY_NOTIFICATION_SETTINGS);

    if (!raw) {
      return fallback;
    }

    try {
      const parsed = JSON.parse(raw) as Partial<NotificationsSettings>;

      return {
        enabled: parsed.enabled ?? fallback.enabled,
        showPreview: parsed.showPreview ?? fallback.showPreview,
        respectBusyStatus: parsed.respectBusyStatus ?? fallback.respectBusyStatus,
        mutedRooms: normaliseBooleanRecord(parsed.mutedRooms),
        mutedChannels: normaliseNestedBooleanRecord(parsed.mutedChannels),
        roomBaselines: normaliseNumberRecord(parsed.roomBaselines),
        lastReadByChannel: normaliseNestedNumberRecord(parsed.lastReadByChannel)
      };
    } catch {
      return fallback;
    }
  }

  save(settings: NotificationsSettings): void {
    localStorage.setItem(STORAGE_KEY_NOTIFICATION_SETTINGS, JSON.stringify(settings));
  }
}

function normaliseBooleanRecord(value: unknown): Record<string, boolean> {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return {};
  }

  return Object.fromEntries(
    Object.entries(value)
      .filter((entry): entry is [string, boolean] => typeof entry[1] === 'boolean')
  );
}

function normaliseNumberRecord(value: unknown): Record<string, number> {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return {};
  }

  return Object.fromEntries(
    Object.entries(value)
      .filter((entry): entry is [string, number] => typeof entry[1] === 'number' && Number.isFinite(entry[1]))
  );
}

function normaliseNestedBooleanRecord(value: unknown): Record<string, Record<string, boolean>> {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return {};
  }

  return Object.fromEntries(
    Object.entries(value)
      .map(([roomId, channels]) => [roomId, normaliseBooleanRecord(channels)])
  );
}

function normaliseNestedNumberRecord(value: unknown): Record<string, Record<string, number>> {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return {};
  }

  return Object.fromEntries(
    Object.entries(value)
      .map(([roomId, channels]) => [roomId, normaliseNumberRecord(channels)])
  );
}
